Why
Sometimes, you just want to execute an async
call inside a lock
statement.
By default, you cannot accomplish this functionality, the compiler will get really mad at you because you are trying to create context-switching inside a lock
.
I'm not saying that this is the cleanest software design that I could think of, but if you want – you can!
How
Here is how you can work around this issue:
In the below functions, you can notice that they use ManualResetEvent
, it gives them the ability to wait inside the lock
statement although the context-switching. We are simply waiting for the event.
*If your Func throws exception, you will not get in outer try-catch, you need to be aware of it.
Code
public static Task Execute(object lockObject, Func<Task> func)
{
return Task.Run(() =>
{
ManualResetEvent e = new ManualResetEvent(false);
lock (lockObject)
{
bool wait = true;
func().ContinueWith((taskResult) =>
{
wait = false;
e.Set();
});
if (wait)
{
e.WaitOne();
}
}
});
}