问题陈述
我有一个工作线程,基本上扫描文件夹,进入其中的文件,然后睡了一会儿.扫描操作可能需要2-3秒但不多.我正在寻找一种方法来优雅地阻止这个线程.
澄清:我想在线程休眠时停止线程,而不是在扫描时.但是,问题是我不知道线程的当前状态是什么.如果它正在睡觉我想让它立即退出.如果正在扫描,我希望它在尝试阻止的那一刻退出.
尝试解决方案
起初我正在使用睡眠和中断.然后我发现中断并没有真正中断睡眠 - 只有在线程TRIES进入睡眠状态时它才有效.
所以我切换到Monitor Wait&Pulse.然后我发现Pulse只在我实际上在等待时才有效.所以现在我有一个看起来像这样的线程:
while (m_shouldRun)
{
try
{
DoSomethingThatTakesSeveralSeconds();
lock (this)
{
Monitor.Wait(this, 5000);
}
}
catch (ThreadInterruptedException)
{
m_shouldRun = false;
}
}
Run Code Online (Sandbox Code Playgroud)
现在我需要制作我的Stop功能.所以我开始:
public void Stop()
{
m_shouldRun = false;
lock (this)
{
Monitor.Pulse(this);
}
thread.Join();
}
Run Code Online (Sandbox Code Playgroud)
但是这不起作用,因为我可能在线程工作时发出脉冲(虽然它没有等待).所以我添加了Interrupt:
public void Stop()
{
m_shouldRun = false;
thread.Interrupt();
lock (this)
{
Monitor.Pulse(this);
}
thread.Join();
}
Run Code Online (Sandbox Code Playgroud)
另一种选择是使用:
public void Stop()
{
m_shouldRun = false;
while (!thread.Join(1000))
{
lock (this)
{
Monitor.Pulse(this);
}
}
}
Run Code Online (Sandbox Code Playgroud)
这个问题
什么是首选方法?有第三种方法更可取吗?
优雅地停止线程的方法是让它自己完成.所以在worker方法中你可以有一个布尔变量来检查我们是否要中断.默认情况下,它将被设置为false,当您true从主线程设置它时,它将通过断开处理循环来停止扫描操作.
另一种选择是使用事件:
private ManualResetEvent _event = new ManualResetEvent(false);
public void Run()
{
while (true)
{
DoSomethingThatTakesSeveralSeconds();
if (_event.WaitOne(timeout))
break;
}
}
public void Stop()
{
_event.Set();
thread.Join();
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
7227 次 |
| 最近记录: |