我在结束我的一个帖子的工作时遇到了一些问题。首先要做的是这里的应用程序“布局”:
线程1 - 工作线程(C ++ / CLI) - 按预期运行和终止
for(...)
{
try
{
if(TabuStop) return;
System::Threading::Monitor::Enter("Lock1");
//some work, unmanaged code
}
finally
{
if(stop)
{
System::Threading::Monitor::Pulse("Lock1");
}
else
{
System::Threading::Monitor::Pulse("Lock1");
System::Threading::Monitor::Wait("Lock1");
}
}
}
线程2 - 显示结果线程(C#)
while (WorkerThread.IsAlive)
{
lock ("Lock1")
{
if (TabuEngine.TabuStop)
{
Monitor.Pulse("Lock1");
}
else
{
Dispatcher.BeginInvoke(RefreshAction);
Monitor.Pulse("Lock1");
Monitor.Wait("Lock1", 5000);
}
}
// Thread.Sleep(5000);
}
我试图从应用程序主线程中关闭整个事情,如下所示:
TabuEngine.TabuStop = true; //terminates nicely the worker thread and
if (DisplayThread.IsAlive)
{
DisplayThread.Abort();
}
我也试过使用DisplayThread.Interrupt,但它总是在Monitor.Wait上阻塞(“Lock1”,5000);我无法摆脱它。这有什么不对?我该如何执行同步并让它完成它应该做的工作?
//编辑 我现在甚至不确定使用“Lock1”字符串的技巧是否正常工作并且锁定放在同一个对象上。
答案 0 :(得分:2)
使用您可以在MSDN (Example 2)上找到的监视器进行生产者/消费者同步的一个很好的例子。 有两个线程(生产者和消费者,类似于你的情况),但同步是通过引入锁定共享资源的第三类来完成的。示例提供了完整的源代码,因此我没有在此处发布。
答案 1 :(得分:1)
这些是监视器,而不是自动重置或手动重置事件。您需要检查条件才能正确使用等待。否则,如果您在开始等待之前Pulse
,则会错过Pulse
。通常情况下,模式如下:
主题A:
lock(x)
{
... work ....
while(!some_condition)
Monitor.Wait(x)
}
主题B:
lock(x)
{
... other work ...
some_condition = true;
Monitor.Pulse(x)
}
通过在保持锁定的情况下操纵和检查some_condition,我们确保无论脉冲何时发生(在我们开始在A中或之后等待之前),A总是可以做出适当的反应,而不是永远等待已经发生的脉冲。