Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
2.5k views
in Technique[技术] by (71.8m points)

multithreading - Mutex in C# - Synchronization from Unsynchronized Block of Code

I am writing a progam which downloads games from a website as zip archives and extracts them. Since all games are downloaded to the same location before being extracted I am using a Mutex to prevent race conditions when two downloads are going on at the same time. The issue is that I am getting a System.ApplicationException thrown saying: "Object synchronization method was called from an unsynchronized block of code." Everything I have looked at says that this is caused by freeing a Mutex from a thread that does not own it. However, my code Wait's and Releases the Mutex in the same thread.

await Task.Run(async () =>
{
   mutex.WaitOne();
   await DownloadGameAsync(ug, nvm);
   await ExtractGameAsync(ug, nvm);
   nvm.Action = "Done";
   mutex.ReleaseMutex();
});

If I place a breakpoint on the line mutex.ReleaseMutex(); and step over the line it does not cause the exception to be thrown however, removing the breakpoint and running normally causes an exception with every execution.

Should I be approaching this differently (Semaphores) or is my use of async/await causing the issue?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

You cannot use thread-affine synchronization primitives (e.g., a Mutex) with async in the general case. Specifically, your code after the await is not guaranteed to run on the same thread as the thread that acquired the mutex.

I recommend using SemaphoreSlim and its WaitAsync method. SemaphoreSlim is the only BCL synchronization primitive that is guaranteed to work correctly with await. If you need more complex synchronization primitives, Stephen Toub wrote a series of blog posts on the subject that I extended and included in my AsyncEx library.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...