eran otzap
eran otzap

Reputation: 12533

ConfigureAwait(true) not returning on the context it was awaited on

Sample :

 static void Main(string[] args)
 {
     int counter = 0;
     var t = new System.Timers.Timer();
     t.Interval = 3000;
     t.Elapsed += async (sender, e) =>  
     {
        Debug.WriteLine("Before await - Thread : {0} , Counter : {1}", Thread.CurrentThread.ManagedThreadId, counter);
        await Task.Delay(1000).ConfigureAwait(true);
        Debug.WriteLine("Ater await Thread : {0}, Counter : {1} ", Thread.CurrentThread.ManagedThreadId, counter);

         counter++;
         if (counter == 2)
         {
            Debug.WriteLine("Stop");
            t.Stop();
         }
     };

     t.Start();

     Console.ReadKey();
 }   

this always outputs :

 Before await - Thread : 4 , Counter : 0 
 Ater await Thread : 4, Counter : 0  
 Before await - Thread : 5 , Counter : 1 
 Ater await Thread : 4, Counter : 1  

 Stop 

Why didn't it return on the thread await was called on. it does the first time but then the timer runs on thread 5 and is suppose to capture the context for when the async operation ends, and as you can see it returns on thread 4.

Upvotes: 1

Views: 532

Answers (2)

Stephen Cleary
Stephen Cleary

Reputation: 456687

Why didn't it return on the thread await was called on.

await resumes on the same context, not the same thread. Sometimes these are the same - notably in UI applications, the UI context is tied to a specific UI thread. Other times there's no correlation - ASP.NET for example has a request context, which is not tied to a specific thread. In this case, the Console app is using the thread pool context, so the method resumes on a thread pool thread.

is there a way i could associate background threads with a synchronization context ?

This is an extremely rare requirement. Often times developers only think they need this. My first recommendation is to remove the specific threading requirement from whatever code requires it, e.g., replacing ThreadStatic with more modern solutions.

However, if you really must use background threads with synchronization contexts, then you can use AsyncContext.Run from my AsyncEx library.

Upvotes: 4

Eser
Eser

Reputation: 12546

There isn't any synchronization context in console app.

If you run your code in WinForms and you'd see it would work as you expected..

Upvotes: 4

Related Questions