Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it ok to await the same task from multiple threads - is await thread safe?

Is await thread safe? It seems the Task class is thread safe so I guess awaiting it is also thread safe but I haven't found a confirmation anywhere. Also is thread safety a requirement for custom awaiter - I mean for the IsCompleted, GetAwaiter, etc. methods? I.e. if those methods are not thread safe, will await be thread safe? However, I don't expect needing a custom awaiter anytime soon.

An example of user scenario: Let's say I have a background task which returns a result asynchronously, which is then used from multiple threads:

using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks;  namespace scratch1 {     class Foo     {         Task<int> _task;          public Foo()         {             _task = Task.Run(async () => { await Task.Delay(5000); return 5; });         }          // Called from multiple threads         public async Task<int> Bar(int i)         {             return (await _task) + i;         }     }      class Program     {         public static void Main(string[] args)         {             Foo foo = new Foo();              List<Task> tasks = new List<Task>();             foreach (var i in Enumerable.Range(0, 100))             {                 tasks.Add(Task.Run(async () => { Console.WriteLine(await foo.Bar(i)); }));              }              Task.WaitAll(tasks.ToArray());         }     } } 
like image 797
Palo Avatar asked May 29 '13 17:05

Palo


People also ask

Are tasks thread safe?

Task does not guarantee parallel execution. Task does not belong to a Thread or anything like that. They are two separate concepts and should be treated as such. Task represents some work that needs to be done.

Is async await a thread?

The async and await keywords don't cause additional threads to be created. Async methods don't require multithreading because an async method doesn't run on its own thread. The method runs on the current synchronization context and uses time on the thread only when the method is active.

Is asynchronous thread safe?

This code is not thread-safe. Whatever else may be true, InternalFireQueuedAsync is racy if called by multiple threads. If one thread is running the while loop, it may reach a point at which it is empty.

What is task<> in. net core?

The Task class represents a single operation that does not return a value and that usually executes asynchronously. Task objects are one of the central components of the task-based asynchronous pattern first introduced in the . NET Framework 4.


1 Answers

As you alluded to, await is thin enough that it doesn't see threads in the first place.

The code associated with await (the compiler-generated code within the state machine, and the support classes in the BCL) will only ever run on one thread at a time. (it can switch to a different thread when coming back from the awaitable, but the previous run will have already finished)

The actual thread-safety depends on the object you're awaiting.
It must have a thread-safe way to add callbacks (or awaiting it twice at once may break).

In addition, it must call the callback exactly once, or it may break the state machine. (in particular, if it runs its callback on two threads at the same time, things will go horribly wrong)

Task is thread-safe.

like image 161
SLaks Avatar answered Sep 18 '22 19:09

SLaks