这是两部分问题。
首先,假设我有一个在另一个线程中执行的函数:
private AutoResetEvent StopEvent = new AutoResetEvent( false);
public void WorkerThread()
{
while( !StopEvent.WaitOne( 10)) {
a();
b();
c();
}
}
现在我想暂停这个帖子。 Thread.Suspend
是不可能的,因为在调用它之后它无法保证我没有死锁系统。由于暂停“粒度”太大,也不需要等待另一个AutoResetEvent。我提出了两个“解决方案”,但对其中任何一个都不感兴趣(但目前首选#2):
1)到处交错PauseEvent.WaitOne()
:
private AutoResetEvent StopEvent = new AutoResetEvent( false);
private ManualResetEvent PauseEvent = new ManualResetEvent( true);
public void WorkerThread()
{
while( !StopEvent.WaitOne( 10)) {
PauseEvent.WaitOne( 0);
a();
PauseEvent.WaitOne( 0);
b();
PauseEvent.WaitOne( 0);
c();
}
}
2)强制a(),b()和c()抛出MyException
。然后我可以在catch块中等待,直到“resume”按钮单击PauseEvent:
private AutoResetEvent StopEvent = new AutoResetEvent( false);
private AutoResetEvent PauseEvent = new AutoResetEvent( false);
public void WorkerThread()
{
while( !StopEvent.WaitOne( 10)) {
try {
a();
b();
c();
} catch( MyException) {
PauseEvent.WaitOne(); // wait indefinitely until signaled by another thread
}
}
}
(2)看起来真的是这样做的唯一方法,但我想知道是否有人尝试过另一种“暂停”的方法。
其次,我正在惹恼的部分是解决方案#2首先引发异常的好方法。目前,我基本上检测了由(),b()和c()调用的低级代码,以查找要发出信号的事件,告诉他们抛出MyException。这是我所知道的唯一方法,你可以在一个线程上诱导另一个线程的行为。
我真正想知道的是(并且我很确定这是不可能的),在.NET中有一些疯狂的方法让工作线程注册一个事件处理程序,所以当我从GUI中激活事件时,工作线程会立即停止正在执行的操作并执行处理程序?我想我基本上都在寻找类似中断服务程序的东西,就像你通常在微控制器上实现的那样。
答案 0 :(得分:0)
我不知道.Net中存在优先级中断的微控制器式方法。但与此同时,您可能需要考虑一个共享标志,您的线程会不断检查它是否应该暂停或运行。一旦检测到暂停请求,它就可以等待Thread.Sleep
或Timer
检查是否允许运行。也许不像你希望的那样优雅,但它是可预测的并且易于实现。
答案 1 :(得分:0)
在针对这个问题采取一些不同的方法后,我认为我的东西运作良好。我基本上选择#2,因为它利用了AutoResetEvent的基本行为来暂停和恢复。
我的线程运行从Stateless派生的状态机,因此我能够将所有暂停和恢复功能放在基类中,这使我的代码变得干净整洁。我也可以通过覆盖派生类中的方法来获得特定于客户端的功能。
最后,在暂停的粒度和代码的优雅之间存在权衡。我牺牲了粒度,所以我没有在任何地方胡椒WaitOne()
。