I am trying to write an async job which runs in the background. There are two ways of doing it-
[Test]
public async Task method1()
{
Task task = run();
await Task.WhenAll(task);
}
[Test]
public async Task method2()
{
Task task = Task.Run(async() =>
{
await run();
});
await Task.WhenAll(task);
}
public async Task run()
{
Console.WriteLine("Current Thread Name: " + Thread.CurrentThread.Name);
// background thread to print numbers with sleep of 1s
await Task.Run(() =>
{
for (int i = 1; i <= 2; i++)
{
Console.Write(i + " ");
Thread.Sleep(1000);
}
Console.WriteLine();
});
}
method1
prints
Current Thread Name: NonParallelWorker
1 2
where as method2
prints
Current Thread Name: .NET TP Worker
1 2
I was wondering what is the difference between these 2 approaches and how it will impact my application. Functionally, both kind of accomplish the same thing - running a job in background asynchronously.
The Task.Run
method invokes an action on the ThreadPool
, and returns a Task
that represents the completion of this action. In case the action is asynchronous, as in your case, the Task.Run
still invokes the action on the ThreadPool
, and returns a proxy Task
that represents both the creation of the inner task and then the completion of this task. If you are interested in more details, you can read this Microsoft article.
If you want to offload a piece of synchronous code to the ThreadPool
, wrapping it once in Task.Run
is enough. Wrapping it twice or more, adds nothing but friction:
// Exercise to futility
Task task = Task.Run(async () =>
{
await Task.Run(async () =>
{
await Task.Run(async () =>
{
await Task.Run(async () =>
{
await Task.Run(async () =>
{
await run();
});
});
});
});
});
I was wondering what is the difference between these 2 approaches and how it will impact my application.
Wrapping two Task.Run
s the one inside the other will make no observable difference. The impact in performance is unlikely to be noticeable. .NET's ThreadPool
is a very efficient piece of software, and can handle such misuse with ease.