【发布时间】:2018-02-26 12:58:07
【问题描述】:
尝试这样做,但得到了SynchronizationLockException。
static object blockObj = new object();
async void Method()
{
await Task.Run(() =>
{
try
{
bool status = Monitor.TryEnter(blockObj);
Debug.WriteLine("Block status: " + (!status).ToString());
if (!status)
{
Monitor.Wait(blockObj, 7000);//got SynchronizationLockException
Debug.WriteLine("Other did the job");
return;
}
else
{
//Imitation of activity
Thread.Sleep(3000);
Monitor.PulseAll(blockObj);
Debug.WriteLine("Completed");
}
}
finally
{
if (Monitor.IsEntered(blockObj))
Monitor.Exit(blockObj);
}
});
}
有没有办法通知代码执行完成?
【问题讨论】:
-
您需要为
Wait和Pulse获取锁(输入监视器)。现在你试图Wait当你没有被锁定时(status= false)所以它失败了。 -
顺便说一句,将
Task与Monitor混合会带来麻烦。如果要使用线程,请使用线程。如果您要使用任务,请使用AsyncMonitor之类的内容。 (或TaskCompletionSource/*EventSlim,如果没有与监视器关联的条件。) -
我需要通知完全解锁的线程。你知道如何正确地做到这一点吗?
-
您可能对监视器的工作方式感到困惑。请注意,
Monitor.Wait调用会隐式释放锁,并在Wait返回时重新获取锁。没有必要对当前未获取的监视器做任何事情,除了获取它。如果您想知道另一个线程是否执行了工作,请设置一个变量并在lock中检查其值——PulseAll仅通知当前正在等待的线程。如果您当前对Monitor的使用没有达到您想要的效果,您将不得不更笼统地描述您的问题。 -
典型的模式是
lock (monitor) { while (!someConditionIsMet) monitor.Wait(); }来自一个地方,lock (monitor) { someConditionIsMet = true; Monitor.PulseAll(monitor); }来自另一个地方。通过设置条件变量“通知”不在监视器上等待的线程(然后它们不会等待)。
标签: c# multithreading synchronization