async Task DoSomethingAsync()
{
    int val = 13;

    // Asynchroniczne oczekiwanie przez 1 sekundę.
    await Task.Delay(TimeSpan.FromSeconds(1));

    val *= 2;

    // Asynchroniczne oczekiwanie przez 1 sekundę.
    await Task.Delay(TimeSpan.FromSeconds(1));

    Trace.WriteLine(val);
}

---

async Task DoSomethingAsync()
{
    int val = 13;

    // Asynchroniczne oczekiwanie przez 1 sekundę.
    await Task.Delay(TimeSpan.FromSeconds(1)).ConfigureAwait(false);

    val *= 2;

    // Asynchroniczne oczekiwanie przez 1 sekundę.
    await Task.Delay(TimeSpan.FromSeconds(1)).ConfigureAwait(false);

    Trace.WriteLine(val.ToString());
}

---

async Task TrySomethingAsync()
{
    try
    {
        await PossibleExceptionAsync();
    }
    catch (NotSupportedException ex)
    {
        LogException(ex);
        throw;
    }
}

---

async Task TrySomethingAsync()
{
    // Wyjątek zostanie ostatecznie umieszczony w typie Task, a nie rzucony bezpośrednio.
    Task task = PossibleExceptionAsync();

    try
    {
        // Tutaj powstanie wyjątek typu Task, przy await.
        await task;
    }
    catch (NotSupportedException ex)
    {
        LogException(ex);
        throw;
    }
}

---

async Task WaitAsync()
{
    // To await przechwyci bieżący kontekst…
    await Task.Delay(TimeSpan.FromSeconds(1));
    // …i spróbuje wznowić wykonywanie metody tutaj, w tym kontekście.
}

void Deadlock()
{
    // Rozpoczęcie wstrzymania.
    Task task = WaitAsync();

    // Synchroniczne blokowanie i oczekiwanie na zakończenie metody async.
    task.Wait();
}

---

void RotateMatrices(IEnumerable<Matrix> matrices, float degrees)
{
    Parallel.ForEach(matrices, matrix => matrix.Rotate(degrees));
}

---

IEnumerable<bool> PrimalityTest(IEnumerable<int> values)
{
    return values.AsParallel().Select(val => IsPrime(val));
}

---

void ProcessArray(double[] array)
{
    Parallel.Invoke(
        () => ProcessPartialArray(array, 0, array.Length / 2),
        () => ProcessPartialArray(array, array.Length / 2, array.Length)
    );
}

void ProcessPartialArray(double[] array, int begin, int end)
{
    // Przetwarzanie intensywne obliczeniowo…
}

---

try
{
    Parallel.Invoke(() => { throw new Exception(); },
        () => { throw new Exception(); });
}
catch (AggregateException ex)
{
    ex.Handle(exception =>
    {
        Trace.WriteLine(exception);
        return true; // "obsłużone"
    });
}

---

interface IObserver<in T>
{
    void OnNext(T item);
    void OnCompleted();
    void OnError(Exception error);
}
interface IObservable<out T>
{
    IDisposable Subscribe(IObserver<T> observer);
}

---

Observable.Interval(TimeSpan.FromSeconds(1))
    .Timestamp()
    .Where(x => x.Value % 2 == 0)
    .Select(x => x.Timestamp)
    .Subscribe(x => Trace.WriteLine(x));

---

IObservable<DateTimeOffset> timestamps =
    Observable.Interval(TimeSpan.FromSeconds(1))
    .Timestamp()
    .Where(x => x.Value % 2 == 0)
    .Select(x => x.Timestamp);
timestamps.Subscribe(x => Trace.WriteLine(x));

---

Observable.Interval(TimeSpan.FromSeconds(1))
    .Timestamp()
    .Where(x => x.Value % 2 == 0)
    .Select(x => x.Timestamp)
    .Subscribe(x => Trace.WriteLine(x),
        ex => Trace.WriteLine(ex));

---

try
{
    var multiplyBlock = new TransformBlock<int, int>(item =>
    {
        if (item == 1)
            throw new InvalidOperationException("Fuj.");
        return item * 2;
    });
    var subtractBlock = new TransformBlock<int, int>(item => item - 2);
    multiplyBlock.LinkTo(subtractBlock,
        new DataflowLinkOptions { PropagateCompletion = true });

    multiplyBlock.Post(1);
    subtractBlock.Completion.Wait();
}
catch (AggregateException exception)
{
    AggregateException ex = exception.Flatten();
    Trace.WriteLine(ex.InnerException);
}

---


