public Task FooAsync() { var tcs = new TaskCompletionSource (); public async Task Task Delay(int Task RunAsync(Func RunStoryboardAsync(this WaitForClickAsync(this milliseconds) func) Button Storyboard button) sb) { var tcs = new TaskCompletionSource (); TaskCompletionSource (); // schedule something asynchronously // to invoke tcs.Set* RoutedEventHandler EventHandler ThreadPool.QueueUserWorkItem(delegate new Timer(_ => tcs.SetResult(true)).Change(milliseconds, handler handler =
Download
Report
Transcript public Task FooAsync() { var tcs = new TaskCompletionSource (); public async Task Task Delay(int Task RunAsync(Func RunStoryboardAsync(this WaitForClickAsync(this milliseconds) func) Button Storyboard button) sb) { var tcs = new TaskCompletionSource (); TaskCompletionSource (); // schedule something asynchronously // to invoke tcs.Set* RoutedEventHandler EventHandler ThreadPool.QueueUserWorkItem(delegate new Timer(_ => tcs.SetResult(true)).Change(milliseconds, handler handler =
public Task<T> FooAsync()
{
var tcs = new TaskCompletionSource<T>();
public async
Task<T>
Task
Delay(int
Task
RunAsync(Func<T>
RunStoryboardAsync(this
WaitForClickAsync(this
milliseconds)
func)
Button
Storyboard
button)
sb)
{
var tcs = new TaskCompletionSource<bool>();
TaskCompletionSource<T>();
// schedule something asynchronously
// to invoke tcs.Set*
RoutedEventHandler
EventHandler<object>
ThreadPool.QueueUserWorkItem(delegate
new
Timer(_ => tcs.SetResult(true)).Change(milliseconds,
handler
handler
= (s,e)
= (s,e)
=>=>
{ tcs.SetResult(true);
tcs.SetResult(true);
-1);
sb.Completed
button.Click
try { tcs.SetResult(func());
+= handler; sb.Begin();
}
catch (Exception e) { tcs.SetException(e); }
}); tcs.Task;
await
sb.Completed
return
button.Click
tcs.Task;
-= handler;
return tcs.Task;
}
}
public async Task FooAsync()
{
…
await SomeDotNetAsync();
await SomeWinRTAsync();
…
}
public async Task FooAsync(CancellationToken cancellationToken)
{
…
await SomeDotNetAsync(cancellationToken);
await SomeWinRTAsync().AsTask(cancellationToken);
…
}
await task;
// force continuation back to the current sync context
await task.ConfigureAwait(false); // try to continue executing where awaited task completes
async void button1_Click(…)
{
await DoWorkAsync();
DoWorkAsync().Wait();
}
async Task DoWorkAsync()
{
await Task.Run(…).ConfigureAwait(false);
Task.Run(…);
Console.WriteLine("Done task");
}
2. Task.Run schedules work
3. Await captures
to run on thread pool
SynchronizationContext and
DoWorkAsync-returned hooks up a continuation to run
when task completes
Task to complete
6. UI thread still blocked
5. Task.Run task completes on pool & invokes
waiting for async
continuation which Posts back to UI thread
operation to complete.
Deadlock!
1. DoWorkAsync
invoked on UI thread 4. UI blocks waiting for
.ConfigureAwait(false) avoids deadlock.
Synchronous
Asynchronous
public static void PausePrint() {
var end = DateTime.Now +
TimeSpan.FromSeconds(10);
while(DateTime.Now < end);
Console.WriteLine("Hello");
}
public static void
Task PausePrintAsync() {
“async=>
ThreadPool.QueueUserWorkItem(_
return
Task.Run(() =>
over
PausePrint());
sync”
}
public static void PausePrint() {
Task t = PausePrintAsync();
t.Wait();
}
Task PausePrintAsync()
{
public static async
Task PausePrintAsync()
{
var tcs
= new TaskCompletionSource<bool>();
await
Task.Delay(10000);
new Timer(_ => {
Console.WriteLine("Hello");
Console.WriteLine("Hello");
}
tcs.SetResult(true);
}).Change(10000, Timeout.Infinite);
return tcs.Task;
}
“sync
over
async”