【问题标题】:How I can inform unlocked thread (Monitor.Wait(), PulseAll() analog)我如何通知未锁定的线程(Monitor.Wait()、PulseAll() 模拟)
【发布时间】: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);
        }
    });
}

有没有办法通知代码执行完成?

【问题讨论】:

  • 您需要为WaitPulse 获取锁(输入监视器)。现在你试图Wait 当你没有被锁定时(status = false)所以它失败了。
  • 顺便说一句,将TaskMonitor 混合会带来麻烦。如果要使用线程,请使用线程。如果您要使用任务,请使用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


【解决方案1】:

我没有找到使用Monitor 通知未锁定线程的方法。尝试使用Thread.Join() 走另一条路。这是我想出的:

public static void Synchronize()
{
    if (th1 == null || !th1.ThreadState.In(System.Threading.ThreadState.Running, System.Threading.ThreadState.WaitSleepJoin))
    {
        Debug.WriteLine("Starting new thread...");
        th1 = new Thread(new ThreadStart(thr_sync));
        th1.Start();
    }
    else
        Debug.WriteLine("Thread is already started. Waiting for the end...");

    if (th1.Join(10000))
        Debug.WriteLine("Done");
    else
        Debug.WriteLine("Time out");
}
static void thr_sync()
{
    //Imitation of activity
    Thread.Sleep(3000);
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-08-07
    • 2014-06-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-07
    相关资源
    最近更新 更多