I ran into an issue today that took me a while to figure out what was happening so I thought I'd share.
I wanted to take advantage of the asynchronous function: NamedPipeServerStream WaitForConnectionAsync to create a multi client Named Pipe server. I also wanted to prevent other instances of the server running so I used a Mutex like this:
//Named pipe server run method
public async Task Run()
{
using (var mutex = new Mutex(true, mutexName, out var createdNew))
{
if (createdNew)
{
try
{
await RunInternal();
}
finally
{
mutex.ReleaseMutex();
}
}
}
}
Everything looked and ran normally until the RunInternal method completed. The call to ReleaseMutex was throwing a synchronization exception:
ApplicationException: Object synchronization method was called from an unsynchronized block of code.
I didn't realize (or appreciate) that the await keyword returns control on a different
thread. Although method looks continuous, the Mutex was right to
complain that a thread that didn't create the Mutex was trying to release it.
public void Run()
{
using (var mutex = new Mutex(true, mutexName, out var createdNew))
{
if (createdNew)
{
try
{
//Synchronously wait so that the finally block executes in current thread.
//This is a requirement of the Mutex.ReleaseMutex method.
RunInternal().Wait();
}
finally
{
mutex.ReleaseMutex();
}
}
}
}
}
Maybe there's better solution but this worked for me, much more to learn I'm sure.
No comments:
Post a Comment