In C# what is the difference between these two statements? If I use the first one in my constructor in my test classes I get a deadlock, or something similar, and the tests never finish. With the second one the code works.
// Deadlock.
var r = MyMethod().Result;
// Works.
var r = Task.Run(() => MyMethod()).Result;
Update: There is a bit more context in this commit: https://github.com/webCRMdotcom/erp-integrations/pull/92/commits/dd8af89899ce1de837ef6e34f0688a685a5cea3b.
Task. Run(action) internally uses the default TaskScheduler , which means it always offloads a task to the thread pool. StartNew(action) , on the other hand, uses the scheduler of the current thread which may not use thread pool at all!
First of all, when you call an async method with Task. Run() , it will not pass on the current synchronization context to the async method. That means that when the async method continues after an await , it will not continue on the main thread in a WinForms application (for example).
async, await, and TaskThe await keyword waits for the async method until it returns a value. So the main application thread stops there until it receives a return value. The Task class represents an asynchronous operation and Task<TResult> generic class represents an operation that can return a value.
GetAwaiter(). GetResult()" is presented as a good way to replace ". Result" and ". Wait()" when we can't use async/await.
The difference is the starting thread context.
Here a simple sample
using System;
using System.Threading.Tasks;
public class Program
{
public static void Main()
{
string r;
OutputThreadInfo("Main");
r = MyMethod().Result;
r = Task.Run( () => MyMethod() ).Result;
}
public static async Task<string> MyMethod()
{
OutputThreadInfo("MyMethod");
await Task.Delay(50);
return "finished";
}
private static void OutputThreadInfo(string context)
{
Console.WriteLine("{0} {1}",context,System.Threading.Thread.CurrentThread.ManagedThreadId);
}
}
.net fiddle
which will output
Main 32 MyMethod 32 MyMethod 63
The first call of MyMethod will start at the same thread as Main and if started from a thread with a synchronization context it will block.
The second call of MyMethod will start from a different thread (worker thread from thread pool) as Main which does not have a synchronization context and therefor will not block.
PS You should keep in mind that Console applications do not have a synchronization context as default but WinForms, WPF, UWP application do have and so will behave somehow different on async/await
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