static async Task<T> DelayResult<T>(T result, TimeSpan delay)
{
    await Task.Delay(delay);
    return result;
}

---

static async Task<string> DownloadStringWithRetries(string uri)
{
    using (var client = new HttpClient())
    {
        // Ponowienie po 1 sekundzie, potem po 2 sekundach, a następnie po 4.
        var nextDelay = TimeSpan.FromSeconds(1);
        for (int i = 0; i != 3; ++i)
        {
            try
            {
                return await client.GetStringAsync(uri);
            }
            catch
            {
            }

            await Task. Delay(nextDelay);
            nextDelay = nextDelay + nextDelay;
        }

        // Próbujemy po raz ostatni, pozwalając na propagowanie błędu.
        return await client.GetStringAsync(uri);
    }
}

---

static async Task<string> DownloadStringWithTimeout(string uri)
{
    using (var client = new HttpClient())
    {
        var downloadTask = client. GetStringAsync(uri);
        var timeoutTask = Task.Delay(3000);

        var completedTask = await Task.WhenAny(downloadTask, timeoutTask);
        if (completedTask == timeoutTask)
            return null;
        return await downloadTask;
    }
}

---

interface IMyAsyncInterface
{
    Task<int> GetValueAsync();
}

class MySynchronousImplementation : IMyAsyncInterface
{
    public Task<int> GetValueAsync()
    {
        return Task.FromResult(13);
    }
}

---

static Task<T> NotImplementedAsync<T>()
{
    var tcs = new TaskCompletionSource<T>();
    tcs.SetException(new NotImplementedException());
    return tcs.Task;
}

---

private static readonly Task<int> zeroTask = Task.FromResult(0);
static Task<int> GetValueAsync()
{
    return zeroTask;
}

---

static async Task MyMethodAsync(IProgress<double> progress = null)
{
    double percentComplete = 0;
    while (!done)
    {
        ...
        if (progress != null)
            progress.Report(percentComplete);
    }
}

---

static async Task CallMyMethodAsync()
{
    var progress = new Progress<double>();
    progress.ProgressChanged += (sender, args) =>
    {
        ...
    };
    await MyMethodAsync(progress);
}

---

Task task1 = Task.Delay(TimeSpan.FromSeconds(1));
Task task2 = Task.Delay(TimeSpan.FromSeconds(2));
Task task3 = Task.Delay(TimeSpan.FromSeconds(1));

await Task.WhenAll(task1, task2, task3);

---

Task task1 = Task.FromResult(3);
Task task2 = Task.FromResult(5);
Task task3 = Task.FromResult(7);

int[] results = await Task.WhenAll(task1, task2, task3);

// "results" zawiera {3, 5, 7}

---

static async Task<string> DownloadAllAsync(IEnumerable<string> urls)
{
    var httpClient = new HttpClient();

    // Definiujemy, co zamierzamy zrobić dla każdego adresu URL.
    var downloads = urls.Select(url => httpClient.GetStringAsync(url));
    // Zwróć uwagę, że w rzeczywistości żadne zadanie nie zostało jeszcze uruchomione,
    // ponieważ sekwencja nie została poddana ewaluacji.

    // Rozpoczęcie pobierania jednocześnie zawartości wszystkich adresów URL.
    Task<string>[] downloadTasks = downloads.ToArray();
    // Teraz wszystkie zadania zostały uruchomione.

    // Asynchroniczne oczekiwanie na ukończenie wszystkich operacji pobierania.
    string[] htmlPages = await Task.WhenAll(downloadTasks);

    return string. Concat(htmlPages);
}

---

static async Task ThrowNotImplementedExceptionAsync()
{
    throw new NotImplementedException();
}

static async Task ThrowInvalidOperationExceptionAsync()
{
    throw new InvalidOperationException();
}

static async Task ObserveOneExceptionAsync()
{
    var task1 = ThrowNotImplementedExceptionAsync();
    var task2 = ThrowInvalidOperationExceptionAsync();

    try
    {
        await Task.WhenAll(task1, task2);
    }
    catch (Exception ex)
    {
        // "ex" to NotImplementedException lub InvalidOperationException.
        ...
    }
}

static async Task ObserveAllExceptionsAsync()
{
    var task1 = ThrowNotImplementedExceptionAsync();
    var task2 = ThrowInvalidOperationExceptionAsync();

    Task allTasks = Task.WhenAll(task1, task2);
    try
    {
        await allTasks;
    }
    catch
    {
        AggregateException allExceptions = allTasks.Exception;
        ...
    }
}

---

// Zwraca długość danych w pierwszym adresie URL, który odpowie.
private static async Task<int> FirstRespondingUrlAsync(string urlA, string urlB)
{
    var httpClient = new HttpClient();

    // Rozpoczyna oba pobierania współbieżnie.
    Task<byte[]> downloadTaskA = httpClient.GetByteArrayAsync(urlA);
    Task<byte[]> downloadTaskB = httpClient.GetByteArrayAsync(urlB);

    // Oczekiwanie na zakończenie któregokolwiek z zadań.
    Task<byte[]> completedTask =
        await Task.WhenAny(downloadTaskA, downloadTaskB);
 
    // Zwraca długość danych pobranych z tego adresu URL.
    byte[] data = await completedTask;
    return data.Length;
}

---

static async Task<int> DelayAndReturnAsync(int val)
{
    await Task.Delay(TimeSpan.FromSeconds(val));
    return val;
}

// Aktualnie ta metoda wyświetla "2", "3" oraz "1".
// Chcemy, aby ta metoda wyświetlała "1", "2" oraz "3".
static async Task ProcessTasksAsync()
{
    // Tworzenie sekwencji zadań.
    Task<int> taskA = DelayAndReturnAsync(2);
    Task<int> taskB = DelayAndReturnAsync(3);
    Task<int> taskC = DelayAndReturnAsync(1);
    var tasks = new[] { taskA, taskB, taskC };

    // Oczekiwanie na każde zadanie w kolejności.
    foreach (var task in tasks)
    {
        var result = await task;
        Trace.WriteLine(result);
    }
}

---

static async Task<int> DelayAndReturnAsync(int val)
{
    await Task.Delay(TimeSpan.FromSeconds(val));
    return val;
}

static async Task AwaitAndProcessAsync(Task<int> task)
{
    var result = await task;
    Trace.WriteLine(result);
}

// Ta metoda wyświetla teraz "1", "2" i "3".
static async Task ProcessTasksAsync()
{
    // Tworzenie sekwencji zadań.
    Task<int> taskA = DelayAndReturnAsync(2);
    Task<int> taskB = DelayAndReturnAsync(3);
    Task<int> taskC = DelayAndReturnAsync(1);
    var tasks = new[] { taskA, taskB, taskC };

    var processingTasks = (from t in tasks
        select AwaitAndProcessAsync(t)).ToArray();

    // Oczekiwanie na zakończenie całego przetwarzania.
    await Task.WhenAll(processingTasks);
}

---

static async Task<int> DelayAndReturnAsync(int val)
{
    await Task.Delay(TimeSpan.FromSeconds(val));
    return val;
}

// Ta metoda wyświetla teraz "1", "2" i "3".
static async Task ProcessTasksAsync()
{
    // Tworzenie sekwencji zadań.
    Task<int> taskA = DelayAndReturnAsync(2);
    Task<int> taskB = DelayAndReturnAsync(3);
    Task<int> taskC = DelayAndReturnAsync(1);
    var tasks = new[] { taskA, taskB, taskC };

    var processingTasks = tasks.Select(async t =>
    {
        var result = await t;
        Trace.WriteLine(result);
    }).ToArray();

    // Oczekiwanie na zakończenie całego przetwarzania.
    await Task.WhenAll(processingTasks);
}

---

static async Task<int> DelayAndReturnAsync(int val)
{
    await Task.Delay(TimeSpan.FromSeconds(val));
    return val;
}

// Ta metoda wyświetla teraz "1", "2" i "3".
static async Task UseOrderByCompletionAsync()
{
    // Tworzenie sekwencji zadań.
    Task<int> taskA = DelayAndReturnAsync(2);
    Task<int> taskB = DelayAndReturnAsync(3);
    Task<int> taskC = DelayAndReturnAsync(1);
    var tasks = new[] { taskA, taskB, taskC };

    // Oczekiwanie na zakończenie każdego z zadań.
    foreach (var task in tasks.OrderByCompletion())
    {
        var result = await task;
        Trace.WriteLine(result);
    }
}

---

async Task ResumeOnContextAsync()
{
    await Task.Delay(TimeSpan.FromSeconds(1));

    // Ta metoda wznawia wykonywanie w tym samym kontekście.
}

async Task ResumeWithoutContextAsync()
{
    await Task.Delay(TimeSpan.FromSeconds(1)).ConfigureAwait(false);

    // Ta metoda porzuca swój kontekst, gdy wznawia wykonywanie.
}

---

static async Task ThrowExceptionAsync()
{
    await Task.Delay(TimeSpan.FromSeconds(1));
    throw new InvalidOperationException("Test" );
}

static async Task TestAsync()
{
    try
    {
        await ThrowExceptionAsync();
    }
    catch (InvalidOperationException)
    {
    }
}

---

static async Task ThrowExceptionAsync()
{
    await Task.Delay(TimeSpan.FromSeconds(1));
    throw new InvalidOperationException("Test" );
}

static async Task TestAsync()
{
    // Wyjątek jest rzucany przez metodę i umieszczany w zadaniu.
    Task task = ThrowExceptionAsync();
    try
    {
        // Wyjątek powstaje tu, gdzie oczekiwane jest zadanie.
        await task;
    }
    catch (InvalidOperationException)
    {
        // Tutaj wyjątek zostaje poprawnie przechwycony.
    }
}

---

sealed class MyAsyncCommand : ICommand
{
    async void ICommand.Execute(object parameter)
    {
        await Execute(parameter);
    }

    public async Task Execute(object parameter)
    {
        ... // Tutaj asynchroniczna implementacja polecenia.
    }

    ... // Pozostałe składowe (CanExecute itp.).
}

---

static class Program
{
    static int Main(string[] args)
    {
        try
        {
            return AsyncContext.Run(() => MainAsync(args));
        }
        catch (Exception ex)
        {
            Console.Error.WriteLine(ex);
            return - 1;
        }
    }

    static async Task<int> MainAsync(string[] args)
    {
        ...
    }
}

---

