shawnmclean/Mandrill-dotnet

Making Call Within Sync ASP.Net Code Causes Deadlock

Closed this issue · 3 comments

I'm trying to send an email synchronously from within a non-async MVC controller action. The email sends successfully, but the thread deadlocks. We are using sessions. It's acting like something is trying to re-enter thread context.

var api = new MandrillApi(key, true);
var result = api.SendMessageTemplate(request).Result; // <-- Deadlock

Using version 2.2.7.0 from Nuget.

This is due to the synchronisation contexts used in ASP.Net, you can't try and block for a result like this. If you really need to wait in a sync fasion, you'll need to do something like:

var result = Task.Run(() => api.SendMessageTemplate(request)).GetAwaiter().GetResult();

I understand why it's happening. However, library code should not attempt to re-enter context.

However, library code should not attempt to re-enter context.

That's how ASP.Net works, it's not related to Mandrill-dotnet.

The root cause of this deadlock is due to the way await handles contexts. By default, when an incomplete Task is awaited, the current “context” is captured and used to resume the method when the Task completes. This “context” is the current SynchronizationContext unless it’s null, in which case it’s the current TaskScheduler. GUI and ASP.NET applications have a SynchronizationContext that permits only one chunk of code to run at a time. When the await completes, it attempts to execute the remainder of the async method within the captured context. But that context already has a thread in it, which is (synchronously) waiting for the async method to complete. They’re each waiting for the other, causing a deadlock.

-- https://msdn.microsoft.com/en-us/magazine/jj991977.aspx