In normal C# we write
int DoSomething(){/*...*/)};
lock(mutex)
{
return DoSomething();
}
to ensure in all cases the mutex
is released.
But if the signature of DoSomething
changed to
Task<int> DoSomeThingAsync(){/*...*/};
Does the following code
return Task.Factory.StartNew(() =>
{
Monitor.Enter(mutex);
return DoSomethingAsync();
}).Unwrap().ContinueWith(t =>
{
Monitor.Exit(mutex);
return t;
}).Unwrap();
do similar things? Is it guaranteed to release the mutex
whenever it was entered? Are there any simpler way to do so? (I am not able to use the async
keyword so keep thinking in TPL only)
You can't use Monitor
in that way because Monitor
is thread-affine and in your case the task and continuation may run on different threads.
The appropriate synchronization mechanism to use is a SemaphoreSlim
(which isn't thread-affine) set to 1:
public SemaphoreSlim _semaphore = new SemaphoreSlim(1,1);
_semaphore.Wait();
return DoSomethingAsync().ContinueWith(t =>
{
_semaphore.Release();
return t.Result;
});
As long as you don't use one of the TaskContinuationOptions
such as OnlyOnFaulted
or OnlyOnCanceled
the continuation would always run after the task has completed and so the semaphore is guaranteed to be released.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With