Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 为什么monitor.exit在其他工作中不起作用?_C#_Multithreading_Asynchronous - Fatal编程技术网

C# 为什么monitor.exit在其他工作中不起作用?

C# 为什么monitor.exit在其他工作中不起作用?,c#,multithreading,asynchronous,C#,Multithreading,Asynchronous,我有一些代码如下: static void Main( string[] args ) { var async = new object(); Monitor.Enter( async ); Task.Run( async () => { await Task.Delay( 5000 ); Monitor.Exit( async ); } );

我有一些代码如下:

static void Main( string[] args )
    {
        var async = new object();

        Monitor.Enter( async );

        Task.Run( async () =>
        {
            await Task.Delay( 5000 );
            Monitor.Exit( async );
        } );

        Monitor.Wait( async );
        Monitor.Exit( async );
    }

但它将在
监视器处阻塞。请永远等待。我可以通过使用信号量来解决这个问题,但我想知道为什么会发生这种情况,以及互斥锁、自旋锁、barrier.thks是怎么回事

监视器
具有线程关联性。您不能从其他线程退出它

但不清楚你到底想在这里做什么。您已经在一个异步方法中,正在调用另一个异步方法。只需使用
await
-只需设置一个同步上下文,即可在控制台应用程序中正确使用
await
。或者,使用
Task.Wait
如果您不担心死锁:)

至于
Monitor.Wait
,它不会做你认为它会做的事情。等待是等待信号,而不是监视器退出。例如:

static readonly object syncObject = new object();

void Thread1()
{
  lock (syncObject) Monitor.Wait(syncObject);
}

void Thread2()
{
  lock (syncObject) Monitor.Pulse(syncObject);
}
在这个场景中,这两个方法都在不同的线程上执行。如果
Thread1
首先运行,它将获取锁,等待信号(在信号出现之前退出锁),并在发出信号后重新获取锁
Thread1
使用
Monitor.Pulse
方法提供信号。请注意,在这两种情况下,锁都在单个线程上执行,并在同一线程上退出

这个机制不是很容易正确使用,而且有点慢,所以你不会经常看到它

另外,
Task.Run
使用的线程不是您的。在线程池线程上使用阻塞代码通常是不可取的——请确保您了解您所做的权衡。更重要的是,任务没有线程亲缘关系-因此使用类似监视器的线程亲缘同步原语是相当冒险的:)在您的情况下,即使您在
任务内部使用锁。运行
而不是在外部,也有可能使
监视器.Exit
失败,因为在
wait
之后,您可能会得到一个不同的线程

不要忘记,多线程最棘手的部分不是它根本不起作用,而是它有一种丑陋的倾向,在大多数情况下都能起作用,并且在奇怪的场景中失败(请注意,在实践中经常发生这种情况)。测试还不足以让您对多线程代码在实践中的行为充满信心。你得到的只是成吨的微小的,几乎不可能复制的虫子。你在这里很幸运-你的代码失败可靠;大多数多线程问题肯定不是这样:)


对于任何类型的多线程编程都有巨大的帮助。我强烈建议至少通读一遍。将其保存在书签中以备将来参考:)

监视器具有线程关联性。您不能从其他线程退出它

但不清楚你到底想在这里做什么。您已经在一个异步方法中,正在调用另一个异步方法。只需使用
await
-只需设置一个同步上下文,即可在控制台应用程序中正确使用
await
。或者,使用
Task.Wait
如果您不担心死锁:)

至于
Monitor.Wait
,它不会做你认为它会做的事情。等待是等待信号,而不是监视器退出。例如:

static readonly object syncObject = new object();

void Thread1()
{
  lock (syncObject) Monitor.Wait(syncObject);
}

void Thread2()
{
  lock (syncObject) Monitor.Pulse(syncObject);
}
在这个场景中,这两个方法都在不同的线程上执行。如果
Thread1
首先运行,它将获取锁,等待信号(在信号出现之前退出锁),并在发出信号后重新获取锁
Thread1
使用
Monitor.Pulse
方法提供信号。请注意,在这两种情况下,锁都在单个线程上执行,并在同一线程上退出

这个机制不是很容易正确使用,而且有点慢,所以你不会经常看到它

另外,
Task.Run
使用的线程不是您的。在线程池线程上使用阻塞代码通常是不可取的——请确保您了解您所做的权衡。更重要的是,任务没有线程亲缘关系-因此使用类似监视器的线程亲缘同步原语是相当冒险的:)在您的情况下,即使您在
任务内部使用锁。运行
而不是在外部,也有可能使
监视器.Exit
失败,因为在
wait
之后,您可能会得到一个不同的线程

不要忘记,多线程最棘手的部分不是它根本不起作用,而是它有一种丑陋的倾向,在大多数情况下都能起作用,并且在奇怪的场景中失败(请注意,在实践中经常发生这种情况)。测试还不足以让您对多线程代码在实践中的行为充满信心。你得到的只是成吨的微小的,几乎不可能复制的虫子。你在这里很幸运-你的代码失败可靠;大多数多线程问题肯定不是这样:)


对于任何类型的多线程编程都有巨大的帮助。我强烈建议至少通读一遍。将其保存在书签中以备将来参考:)

“但它将在监视器上被阻止。永远等待”-是的,没有任何东西在调用
Monitor.Pulse
。不清楚为什么您希望这样做,但是在不拥有监视器的线程上调用
Monitor.Exit
将引发异常。我还强烈建议不要将变量命名为
async
,尤其是在使用async/await的方法中。你到底想做什么?@viveknuna只是为了测试。“但它会在监视器上阻塞。永远等待”-是的,没有调用
Monitor.Pulse
。不清楚为什么您希望这样做,但是在不拥有监视器的线程上调用
Monitor.Exit
将引发异常。我还强烈建议不要将变量命名为async
,尤其是在使用async/await的方法中。你到底想做什么?@viveknuna只是为了