0

I have a code that looks a bit like that. I have a method do_it that does the work and uses some resources that must be protected by a mutex. To do it, I tried using a mutex before calling it, to force other tasks to block until the work is done. But the mutex does not block the second task, and both runs in paralell, I would like to know why, and what is the best way to do it.

using System; using System.Threading; using System.Threading.Tasks; namespace teste_threads { class test_mutex { Mutex mut = new Mutex(); public async Task first() { mut.WaitOne(); await do_it(); mut.ReleaseMutex(); } public async Task second() { mut.WaitOne(); await do_it(); mut.ReleaseMutex(); } public async Task do_it() { await Task.Run(() => doSomething()); } private void doSomething() { Console.WriteLine("doSomething starting"); Thread.Sleep(1000); Console.WriteLine("doSomething ending"); } } class Program { static test_mutex test = new test_mutex(); static void Main(string[] args) { test.first(); Thread.Sleep(100); test.second(); Thread.Sleep(3000); } } } 

I was expecting that the output to this code would be:

doSomething starting doSomething ending doSomething starting doSomething ending 

but instead, I get:

doSomething starting doSomething starting doSomething ending doSomething ending 

that means the mutex is not blocking when second() is called. What is wrong with that mutex?

4
  • 1
    Can you change static void Main() in static async Task Main()? Commented Mar 31, 2021 at 19:25
  • Yes, I can, but it makes no difference Commented Mar 31, 2021 at 19:53
  • 1
    Not if your code remains what it is now. But, in comments, you have provided a completely different description of your intentions and this code appears to be a proof of concept that doesn't really prove or test anything. Async/await here is simply not working. Can you show what you actually want to do where you actually want to do it? Commented Mar 31, 2021 at 20:12
  • You can't use Mutex with await. See duplicate. Note that even if this had worked as you expected as far as waiting goes, the next problem would have been that the async methods likely would have failed to release the mutex, because they would have resumed execution in a different thread. See e.g. stackoverflow.com/questions/20101952/… Commented Mar 31, 2021 at 23:48

2 Answers 2

6

Mutexes - and other synchronous synchronization primitives - cannot be used with asynchronous code. You need asynchronous synchronization primitives.

There is one asynchronous synchronization primitive built-in: SemaphoreSlim, which can be used as an asynchronous mutex as such:

SemaphoreSlim mut = new SemaphoreSlim(1); public async Task first() { await mut.WaitAsync(); try { await do_it(); } finally { mut.Release(); } } public async Task second() { await mut.WaitAsync(); try { await do_it(); } finally { mut.Release(); } } 
Sign up to request clarification or add additional context in comments.

Comments

0

The problem is that both first and second methods are running in the same thread, so your mutex is basicaly not blocking at all.

Try to remove the ReleaseMutex() calls and it will work the same way proving that there are no 2 threads running the code so the Mutex usage is useless.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.