using System;
using System.Threading.Tasks;
using static System.Console;
using static System.Threading.Thread;
namespace Chapter5.Recipe1
{
class Program
{
static void Main(string[] args)
{
Task t = AsynchronyWithTPL();
t.Wait();
t = AsynchronyWithAwait();
t.Wait();
}
static Task AsynchronyWithTPL()
{
Task<string> t = GetInfoAsync("Task 1");
Task t2 = t.ContinueWith(task => WriteLine(t.Result),
TaskContinuationOptions.NotOnFaulted);
Task t3 = t.ContinueWith(task => WriteLine(t.Exception.InnerException),
TaskContinuationOptions.OnlyOnFaulted);
return Task.WhenAny(t2, t3);
}
static async Task AsynchronyWithAwait()
{
try
{
string result = await GetInfoAsync("Task 2");
WriteLine(result);
}
catch (Exception ex)
{
WriteLine(ex);
}
}
static async Task<string> GetInfoAsync(string name)
{
await Task.Delay(TimeSpan.FromSeconds(2));
//throw new Exception("Boom!");
return
$"Task {name} is running on a thread id {CurrentThread.ManagedThreadId}." +
$" Is thread pool thread: {CurrentThread.IsThreadPoolThread}";
}
}
}
using System;
using System.Threading.Tasks;
using static System.Console;
using static System.Threading.Thread;
namespace Chapter5.Recipe2
{
class Program
{
static void Main(string[] args)
{
Task t = AsynchronousProcessing();
t.Wait();
}
static async Task AsynchronousProcessing()
{
Func<string, Task<string>> asyncLambda = async name => {
await Task.Delay(TimeSpan.FromSeconds(2));
return
$"Task {name} is running on a thread id {CurrentThread.ManagedThreadId}." +
$" Is thread pool thread: {CurrentThread.IsThreadPoolThread}";
};
string result = await asyncLambda("async lambda");
WriteLine(result);
}
}
}
using System;
using System.Threading.Tasks;
using static System.Console;
using static System.Threading.Thread;
namespace Chapter5.Recipe3
{
class Program
{
static void Main(string[] args)
{
Task t = AsynchronyWithTPL();
t.Wait();
t = AsynchronyWithAwait();
t.Wait();
}
static Task AsynchronyWithTPL()
{
var containerTask = new Task(() => {
Task<string> t = GetInfoAsync("TPL 1");
t.ContinueWith(task => {
WriteLine(t.Result);
Task<string> t2 = GetInfoAsync("TPL 2");
t2.ContinueWith(innerTask => WriteLine(innerTask.Result),
TaskContinuationOptions.NotOnFaulted | TaskContinuationOptions.AttachedToParent);
t2.ContinueWith(innerTask => WriteLine(innerTask.Exception.InnerException),
TaskContinuationOptions.OnlyOnFaulted | TaskContinuationOptions.AttachedToParent);
},
TaskContinuationOptions.NotOnFaulted | TaskContinuationOptions.AttachedToParent);
t.ContinueWith(task => WriteLine(t.Exception.InnerException),
TaskContinuationOptions.OnlyOnFaulted | TaskContinuationOptions.AttachedToParent);
});
containerTask.Start();
return containerTask;
}
static async Task AsynchronyWithAwait()
{
try
{
string result = await GetInfoAsync("Async 1");
WriteLine(result);
result = await GetInfoAsync("Async 2");
WriteLine(result);
}
catch (Exception ex)
{
WriteLine(ex);
}
}
static async Task<string> GetInfoAsync(string name)
{
WriteLine($"Task {name} started!");
await Task.Delay(TimeSpan.FromSeconds(2));
if(name == "TPL 2")
throw new Exception("Boom!");
return
$"Task {name} is running on a thread id {CurrentThread.ManagedThreadId}." +
$" Is thread pool thread: {CurrentThread.IsThreadPoolThread}";
}
}
}
using System;
using System.Threading.Tasks;
using static System.Console;
using static System.Threading.Thread;
namespace Chapter5.Recipe4
{
class Program
{
static void Main(string[] args)
{
Task t = AsynchronousProcessing();
t.Wait();
}
static async Task AsynchronousProcessing()
{
Task<string> t1 = GetInfoAsync("Task 1", 3);
Task<string> t2 = GetInfoAsync("Task 2", 5);
string[] results = await Task.WhenAll(t1, t2);
foreach (string result in results)
{
WriteLine(result);
}
}
static async Task<string> GetInfoAsync(string name, int seconds)
{
await Task.Delay(TimeSpan.FromSeconds(seconds));
//await Task.Run(() => Thread.Sleep(TimeSpan.FromSeconds(seconds)));
return
$"Task {name} is running on a thread id {CurrentThread.ManagedThreadId}." +
$" Is thread pool thread: {CurrentThread.IsThreadPoolThread}";
}
}
}
using System;
using System.Threading.Tasks;
using static System.Console;
namespace Chapter5.Recipe5
{
class Program
{
static void Main(string[] args)
{
Task t = AsynchronousProcessing();
t.Wait();
}
static async Task AsynchronousProcessing()
{
WriteLine("1. Single exception");
try
{
string result = await GetInfoAsync("Task 1", 2);
WriteLine(result);
}
catch (Exception ex)
{
WriteLine($"Exception details: {ex}");
}
WriteLine();
WriteLine("2. Multiple exceptions");
Task<string> t1 = GetInfoAsync("Task 1", 3);
Task<string> t2 = GetInfoAsync("Task 2", 2);
try
{
string[] results = await Task.WhenAll(t1, t2);
WriteLine(results.Length);
}
catch (Exception ex)
{
WriteLine($"Exception details: {ex}");
}
WriteLine();
WriteLine("3. Multiple exceptions with AggregateException");
t1 = GetInfoAsync("Task 1", 3);
t2 = GetInfoAsync("Task 2", 2);
Task<string[]> t3 = Task.WhenAll(t1, t2);
try
{
string[] results = await t3;
WriteLine(results.Length);
}
catch
{
var ae = t3.Exception.Flatten();
var exceptions = ae.InnerExceptions;
WriteLine($"Exceptions caught: {exceptions.Count}");
foreach (var e in exceptions)
{
WriteLine($"Exception details: {e}");
WriteLine();
}
}
WriteLine();
WriteLine("4. await in catch and finally blocks");
try
{
string result = await GetInfoAsync("Task 1", 2);
WriteLine(result);
}
catch (Exception ex)
{
await Task.Delay(TimeSpan.FromSeconds(1));
WriteLine($"Catch block with await: Exception details: {ex}");
}
finally
{
await Task.Delay(TimeSpan.FromSeconds(1));
WriteLine("Finally block");
}
}
static async Task<string> GetInfoAsync(string name, int seconds)
{
await Task.Delay(TimeSpan.FromSeconds(seconds));
throw new Exception($"Boom from {name}!");
}
}
}
using System;
using System.Diagnostics;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using static System.Console;
namespace Chapter5.Recipe6
{
class Program
{
[STAThread]
static void Main(string[] args)
{
var app = new Application();
var win = new Window();
var panel = new StackPanel();
var button = new Button();
_label = new Label();
_label.FontSize = 32;
_label.Height = 200;
button.Height = 100;
button.FontSize = 32;
button.Content = new TextBlock {Text = "Start asynchronous operations"};
button.Click += Click;
panel.Children.Add(_label);
panel.Children.Add(button);
win.Content = panel;
app.Run(win);
ReadLine();
}
static async void Click(object sender, EventArgs e)
{
_label.Content = new TextBlock {Text = "Calculating..."};
TimeSpan resultWithContext = await Test();
TimeSpan resultNoContext = await TestNoContext();
//TimeSpan resultNoContext = await TestNoContext().ConfigureAwait(false);
var sb = new StringBuilder();
sb.AppendLine($"With the context: {resultWithContext}");
sb.AppendLine($"Without the context: {resultNoContext}");
sb.AppendLine("Ratio: " +
$"{resultWithContext.TotalMilliseconds/resultNoContext.TotalMilliseconds:0.00}");
_label.Content = new TextBlock {Text = sb.ToString()};
}
static async Task<TimeSpan> Test()
{
const int iterationsNumber = 100000;
var sw = new Stopwatch();
sw.Start();
for (int i = 0; i < iterationsNumber; i++)
{
var t = Task.Run(() => { });
await t;
}
sw.Stop();
return sw.Elapsed;
}
static async Task<TimeSpan> TestNoContext()
{
const int iterationsNumber = 100000;
var sw = new Stopwatch();
sw.Start();
for (int i = 0; i < iterationsNumber; i++)
{
var t = Task.Run(() => { });
await t.ConfigureAwait(
continueOnCapturedContext: false);
}
sw.Stop();
return sw.Elapsed;
}
private static Label _label;
}
}
using System;
using System.Threading.Tasks;
using static System.Console;
using static System.Threading.Thread;
namespace Chapter5.Recipe7
{
class Program
{
static void Main(string[] args)
{
Task t = AsyncTask();
t.Wait();
AsyncVoid();
Sleep(TimeSpan.FromSeconds(3));
t = AsyncTaskWithErrors();
while(!t.IsFaulted)
{
Sleep(TimeSpan.FromSeconds(1));
}
WriteLine(t.Exception);
//try
//{
// AsyncVoidWithErrors();
// Thread.Sleep(TimeSpan.FromSeconds(3));
//}
//catch (Exception ex)
//{
// Console.WriteLine(ex);
//}
int[] numbers = {1, 2, 3, 4, 5};
Array.ForEach(numbers, async number => {
await Task.Delay(TimeSpan.FromSeconds(1));
if (number == 3) throw new Exception("Boom!");
WriteLine(number);
});
ReadLine();
}
static async Task AsyncTaskWithErrors()
{
string result = await GetInfoAsync("AsyncTaskException", 2);
WriteLine(result);
}
static async void AsyncVoidWithErrors()
{
string result = await GetInfoAsync("AsyncVoidException", 2);
WriteLine(result);
}
static async Task AsyncTask()
{
string result = await GetInfoAsync("AsyncTask", 2);
WriteLine(result);
}
static async void AsyncVoid()
{
string result = await GetInfoAsync("AsyncVoid", 2);
WriteLine(result);
}
static async Task<string> GetInfoAsync(string name, int seconds)
{
await Task.Delay(TimeSpan.FromSeconds(seconds));
if(name.Contains("Exception"))
throw new Exception($"Boom from {name}!");
return
$"Task {name} is running on a thread id {CurrentThread.ManagedThreadId}." +
$" Is thread pool thread: {CurrentThread.IsThreadPoolThread}";
}
}
}
using System;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;
using static System.Console;
using static System.Threading.Thread;
namespace Chapter5.Recipe8
{
class Program
{
static void Main(string[] args)
{
Task t = AsynchronousProcessing();
t.Wait();
}
static async Task AsynchronousProcessing()
{
var sync = new CustomAwaitable(true);
string result = await sync;
WriteLine(result);
var async = new CustomAwaitable(false);
result = await async;
WriteLine(result);
}
class CustomAwaitable
{
public CustomAwaitable(bool completeSynchronously)
{
_completeSynchronously = completeSynchronously;
}
public CustomAwaiter GetAwaiter()
{
return new CustomAwaiter(_completeSynchronously);
}
private readonly bool _completeSynchronously;
}
class CustomAwaiter : INotifyCompletion
{
private string _result = "Completed synchronously";
private readonly bool _completeSynchronously;
public bool IsCompleted => _completeSynchronously;
public CustomAwaiter(bool completeSynchronously)
{
_completeSynchronously = completeSynchronously;
}
public string GetResult()
{
return _result;
}
public void OnCompleted(Action continuation)
{
ThreadPool.QueueUserWorkItem( state => {
Sleep(TimeSpan.FromSeconds(1));
_result = GetInfo();
continuation?.Invoke();
});
}
private string GetInfo()
{
return
$"Task is running on a thread id {CurrentThread.ManagedThreadId}." +
$" Is thread pool thread: {CurrentThread.IsThreadPoolThread}";
}
}
}
}
using System;
using System.Dynamic;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;
using ImpromptuInterface;
using static System.Console;
using static System.Threading.Thread;
namespace Chapter5.Recipe9
{
class Program
{
static void Main(string[] args)
{
Task t = AsynchronousProcessing();
t.Wait();
}
static async Task AsynchronousProcessing()
{
string result = await GetDynamicAwaitableObject(true);
WriteLine(result);
result = await GetDynamicAwaitableObject(false);
WriteLine(result);
}
static dynamic GetDynamicAwaitableObject(bool completeSynchronously)
{
dynamic result = new ExpandoObject();
dynamic awaiter = new ExpandoObject();
awaiter.Message = "Completed synchronously";
awaiter.IsCompleted = completeSynchronously;
awaiter.GetResult = (Func<string>)(() => awaiter.Message);
awaiter.OnCompleted = (Action<Action>) ( callback =>
ThreadPool.QueueUserWorkItem(state => {
Sleep(TimeSpan.FromSeconds(1));
awaiter.Message = GetInfo();
callback?.Invoke();
})
);
IAwaiter<string> proxy = Impromptu.ActLike(awaiter);
result.GetAwaiter = (Func<dynamic>) ( () => proxy );
return result;
}
static string GetInfo()
{
return
$"Task is running on a thread id {CurrentThread.ManagedThreadId}." +
$" Is thread pool thread: {CurrentThread.IsThreadPoolThread}";
}
}
public interface IAwaiter<T> : INotifyCompletion
{
bool IsCompleted { get; }
T GetResult();
}
}