C#中的互斥体-从未同步的代码块进行同步

C#中的互斥体-从未同步的代码块进行同步,c#,multithreading,async-await,C#,Multithreading,Async Await,我正在写一个程序,从一个网站下载游戏作为zip档案,并提取它们。由于所有游戏在解压之前都下载到同一个位置,所以当两次下载同时进行时,我使用互斥锁来防止出现竞争情况。问题是我得到了一个System.ApplicationException抛出,它说:“对象同步方法是从一个未同步的代码块调用的。”我所看到的一切都表明,这是由于将互斥体从一个不拥有它的线程中释放而导致的。但是,我的代码等待并释放同一线程中的互斥 await Task.Run(async () => { mutex.Wait

我正在写一个程序,从一个网站下载游戏作为zip档案,并提取它们。由于所有游戏在解压之前都下载到同一个位置,所以当两次下载同时进行时,我使用互斥锁来防止出现竞争情况。问题是我得到了一个System.ApplicationException抛出,它说:“对象同步方法是从一个未同步的代码块调用的。”我所看到的一切都表明,这是由于将互斥体从一个不拥有它的线程中释放而导致的。但是,我的代码等待并释放同一线程中的互斥

await Task.Run(async () =>
{
   mutex.WaitOne();
   await DownloadGameAsync(ug, nvm);
   await ExtractGameAsync(ug, nvm);
   nvm.Action = "Done";
   mutex.ReleaseMutex();
});
如果在mutex.ReleaseMutex()行上放置断点;跨行执行不会导致抛出异常,但是,删除断点并正常运行会导致每次执行时出现异常


我应该以不同的方式处理这个问题(信号量),还是使用async/await导致了这个问题?

在一般情况下,不能将线程仿射同步原语(例如,
互斥体)与
async
一起使用。具体地说,
wait
之后的代码不能保证与获取互斥锁的线程在同一个线程上运行

我建议使用
SemaphoreSlim
及其
WaitAsync
方法
SemaphoreSlim
是唯一保证与
Wait
一起正确工作的BCL同步原语。如果你需要更复杂的同步原语,Stephen Toub写了一篇关于这个主题的文章,我将其扩展并包含在我的文章中