MutexApplicationExceptionwhenusingasync/await
c#
I am trying to get the response from a url, and when I use the await and async in my function, my Mutex throws an error.
Error output :
System.ApplicationException
Object synchronization method was called from an unsynchronized block of code.
at System.Threading.Mutex.ReleaseMutex()
Code :
private async void getData ()
{
_mutex.WaitOne();
try
{
string url = "https://urllink.com";
HttpClient client = new HttpClient();
string response = await client.GetStringAsync(url);
}
catch (Exception e)
{
// TODO
throw e;
}
_mutex.ReleaseMutex();
}
回答
I would propose two three changes here:
- replace
async voidwithasync Task(credit: Fildor), and make sure youawaitit - replace
MutexwithSemaphoreSlim(anew SemaphoreSlim(1,1)is basically the same thing as aMutex) - theMutexdocumentation is heavily focused on "the thread that owns the mutex", which strongly suggests it is thread-bound, andawaitis incompatible with thread-bound scenarios;SemaphoreSlim, however, is not thread-bound; additionally, it has an async-awareWaitAsync()API, avoiding thread blocks (i.e. replace_mutex.WaitOne();withawait _semaphore.WaitAsync();) - put the release in a
finally, so that it is released even in the failure case
But "1" seems to be the real problem here. I would also speculate that this code worked fine until it was changed to async.
您也可以删除catch, 因为catch刚刚拥有的 athrow是多余的;一catch,仅仅有throw e;是雪上加霜不是多余的:它打破了堆栈跟踪。
- 您 **不能** 在代码中使用 Mutex,因为 `await` 可能会转换到不同的线程。你**会**有这个问题。您可以将大部分代码保持原样,但您需要更改为没有线程关联的同步对象。[AsyncEx by Stephen Cleary](https://github.com/StephenCleary/AsyncEx) 如果您希望锁获取也是异步的,可以使用很多替代方法。如果这不是问题,您可以按照 Marc 的描述切换到 SemaphoreSlim。
- 我还强烈建议不要使用“async void”,而使用“async Task”。并重用 HttpClient 实例,而不是在每次调用时创建一个新实例。
THE END
二维码