具有异步等待的全局互斥体

inn*_*227 6 c# mutex async-await

我有一个关键的代码段,一次只能由一个进程运行.为确保机器上只有一个进程运行此关键块,我使用全局互斥锁.关键部分中的代码使用async/await.总体而言,代码看起来像这样:

var mutex = new Mutex(false, @"Global\MyMutexName");    
mutex.WaitOne(-1, false);   
SetupASystemWideResource() 
await DoSomeAsyncWorkOnThatResource();    
mutex.ReleaseMutex();
Run Code Online (Sandbox Code Playgroud)

问题是await之后的代码可能发生在不同的线程上.因此,互斥体可以在与获取的不同的线程上发布.这会导致异常

System.ApplicationException: Object synchronization method was called from an unsynchronized block of code.
Run Code Online (Sandbox Code Playgroud)

通常这会使你因为你不想要一个不同的线程释放互斥锁而不是获取它.但是在我的情况下,我真的只想防止应用程序的第二个实例在第一个实例使用它时以不同的方式设置系统资源.资源本身可以在一个实例中的多个线程中使用.

确保这一点并以异步方式完成工作的正确方法是什么?

AAA*_*ddd 4

如果我理解问题,并且这是一个控制台应用程序或者没有同步上下文,只需调用Wait,就不用担心死锁,它应该可以正常工作

var mutex = new Mutex(false, @"Global\MyMutexName");    
mutex.WaitOne(-1, false);

DoSomeAsyncWorkOnThatResource().Wait();
mutex.ReleaseMutex();
Run Code Online (Sandbox Code Playgroud)

或者如果你真的必须(而且更有争议)你可以使用

Task.Run(async () => await DoSomeAsyncWorkOnThatResource()).Wait();
Run Code Online (Sandbox Code Playgroud)

您可以做的另一件事是使用自定义调度程序CurrentThreadTaskScheduler(我第一次看到您使用它),如Stephen Toubs Parallel Planning with .NET中所述。Nuget 并行扩展额外

当请求调度时,运行当前线程上的所有任务

并将其与Task.Factory.StartNew需要调度程序的东西一起使用