/// <summary> /// This will "seems" that is working, but taking deeper look, we can see that actually an error was thrown (use the debugger). /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void MakeTeaAsyncUsingTPLNoDispatcher_OnClick(object sender, RoutedEventArgs e) { BeforeMakingTea(); Task.Run(async() => { _finalMessage = new StringBuilder(); _finalMessage.AppendLine("Making tea started."); _finalMessage.AppendLine(await MakeTeaAsync.MakeMeTeaAsync()); Notes.Text = _finalMessage.ToString(); }); AfterMakingTea(); }
/// <summary> /// Will make the tea in a async way. /// The UI thread is available again and we can perform any actions while the code is been executed somewhere else. /// This will introduce a state machine and a continuation. /// Once the job is done, the UI thread will update the finalMessasge text /// And carry on with the following piece of code. /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private async void MakeTeaAsynchronous_OnClick(object sender, RoutedEventArgs e) { // UI Thread BeforeMakingTea(); _finalMessage = new StringBuilder(); _finalMessage.AppendLine("Making tea started."); // Will spin a new thread and the UI thread is released from the work. _finalMessage.AppendLine(await MakeTeaAsync.MakeMeTeaAsync()); Notes.Text = _finalMessage.ToString(); AfterMakingTea(); }
/// <summary> /// This will crash the application /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private async void MakeTeaAsynchronousConfigureAwaitFalse_OnClick(object sender, RoutedEventArgs e) { BeforeMakingTea(); _finalMessage = new StringBuilder(); _finalMessage.AppendLine("Making tea started."); // Adding ConfigureAwait false, will indicate that we don't care that the continuation been executed in a different thread. // Because this is a UI component, we can see that we are trying to update the UI with something, and because we are // in a different thread in the continuation, the application will crash. _finalMessage.AppendLine(await MakeTeaAsync.MakeMeTeaAsync().ConfigureAwait(false)); Notes.Text = _finalMessage.ToString(); AfterMakingTea(); }
/// <summary> /// This scenario will cause a Deadlock. See GiveMeStringFromAnInt() for a more info. /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private async void MakeTeaAsyncDeadlock_OnClick(object sender, RoutedEventArgs e) { BeforeMakingTea(); try { _finalMessage = new StringBuilder(); _finalMessage.AppendLine("Making tea started."); MakeTeaAsync.MakeMeTeaAsync().Wait(); // Now comment the above Wait() and try the below line instead. // var result = MakeTeaAsync.MakeMeTeaAsync().Result; _finalMessage.AppendLine("After calling the method async"); Notes.Text = _finalMessage.ToString(); } catch (Exception exception) { Notes.Text = exception.Message; } AfterMakingTea(); }
/// <summary> /// This example will achieve the same as above but without adding any async and await keyword. /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void MakeTeaAsyncUsingTPLDispatcherContinuation_OnClick(object sender, RoutedEventArgs e) { BeforeMakingTea(); var makeTeaTask = Task.Run(async() => { _finalMessage = new StringBuilder(); _finalMessage.AppendLine("Making tea started."); _finalMessage.AppendLine(await MakeTeaAsync.MakeMeTeaAsync()); Dispatcher.Invoke(() => { Notes.Text = _finalMessage.ToString(); }); }); makeTeaTask.ContinueWith(_ => { Dispatcher.Invoke(AfterMakingTea); }); }
private void MakeTeaAsyncUsingTPLCancellationSecondAttempt_OnClick(object sender, RoutedEventArgs e) { if (cancellationTokenSource != null) { // Already have an instance of the cancellation token source? // This means the button has already been pressed! cancellationTokenSource.Cancel(); cancellationTokenSource = null; TplCancellationSecondButton.Content = "TPL - Cancellation 2"; return; } cancellationTokenSource = new CancellationTokenSource(); TplCancellationSecondButton.Content = "Cancel"; BeforeMakingTea(); var makeTeaTask = Task.Run(async() => { _finalMessage = new StringBuilder(); _finalMessage.AppendLine("Making tea started."); _finalMessage.AppendLine(await MakeTeaAsync.MakeMeTeaAsync()); Dispatcher.Invoke(() => { Notes.Text = _finalMessage.ToString(); }); }, cancellationTokenSource.Token); makeTeaTask.ContinueWith(_ => { Dispatcher.Invoke(AfterMakingTea); cancellationTokenSource = null; TplCancellationSecondButton.Content = "TPL - Cancellation 2"; }); }