static int _simpleValue;
static readonly Lazy<int> MySharedInteger = new Lazy<int>(() => _simpleValue++);

void UseSharedInteger()
{
    int sharedValue = MySharedInteger.Value;
}

---

static int _simpleValue;
static readonly Lazy<Task<int>> MySharedAsyncInteger =
    new Lazy<Task<int>>(async () =>
    {
        await Task.Delay(TimeSpan.FromSeconds(2)).ConfigureAwait(false);
        return _simpleValue++;
    });

async Task GetSharedIntegerAsync()
{
    int sharedValue = await MySharedAsyncInteger.Value;
}

---

static readonly Lazy<Task<int>> MySharedAsyncInteger = new Lazy<Task<int>>(
    () => Task.Run(
        async () =>
        {
            await Task.Delay(TimeSpan.FromSeconds(2));
            return _simpleValue++;
        }));

---

private static readonly AsyncLazy<int> MySharedAsyncInteger =
    new AsyncLazy<int>(async () =>
    {
        await Task.Delay(TimeSpan.FromSeconds(2));
        return _simpleValue++;
    });

public async Task UseSharedIntegerAsync()
{
    int sharedValue = await MySharedAsyncInteger;
}

---

static void Main(string[] args)
{
    var invokeServerObservable = Observable.Defer(
        () => GetValueAsync().ToObservable());
    invokeServerObservable.Subscribe(_ => { });
    invokeServerObservable.Subscribe(_ => { });

    Console.ReadKey();
}

static async Task<int> GetValueAsync()
{
    Console.WriteLine("Wywoływanie serwera..." );
    await Task.Delay(TimeSpan.FromSeconds(2));
    Console.WriteLine("Zwracanie wyniku..." );
    return 13;
}

---

class MyViewModel
{
    public MyViewModel()
    {
        MyValue = NotifyTaskCompletion.Create(CalculateMyValueAsync());
    }

    public INotifyTaskCompletion<int> MyValue { get; private set; }

    private async Task<int> CalculateMyValueAsync()
    {
        await Task.Delay(TimeSpan.FromSeconds(10));
        return 13;
    }
}

---

<Grid>
    <Label Content="Ładowanie..."
        Visibility="{Binding MyValue.IsNotCompleted,
            Converter={StaticResource BooleanToVisibilityConverter}}" />
    <Label Content="{Binding MyValue.Result}"
        Visibility="{Binding MyValue.IsSuccessfullyCompleted,
            Converter={StaticResource BooleanToVisibilityConverter}}" />
    <Label Content="Wystąpił błąd" Foreground="Red"
        Visibility="{Binding MyValue.IsFaulted,
            Converter={StaticResource BooleanToVisibilityConverter}}" />
</Grid>

---

class BindableTask<T> : INotifyPropertyChanged
{
    private readonly Task<T> _task;

    public BindableTask(Task<T> task)
    {
        _task = task;
        var _ = WatchTaskAsync();
    }

    private async Task WatchTaskAsync()
    {
        try
        {
            await _task;
        }
        catch
        {
        }

        OnPropertyChanged("IsNotCompleted" );
        OnPropertyChanged("IsSuccessfullyCompleted" );
        OnPropertyChanged("IsFaulted" );
        OnPropertyChanged("Result" );
    }

    public bool IsNotCompleted { get { return !_task.IsCompleted; } }
    public bool IsSuccessfullyCompleted
    { get { return _task.Status == TaskStatus.RanToCompletion; } }
    public bool IsFaulted { get { return _task.IsFaulted; } }
    public T Result
    { get { return IsSuccessfullyCompleted ? _task.Result : default(T); } }

    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged(string propertyName)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
            handler(this, new PropertyChangedEventArgs(propertyName));
    }
}

---

void DoLongOperation()
{
    var operationId = Guid.NewGuid();
    CallContext.LogicalSetData("OperationId" , operationId);

    DoSomeStepOfOperation();

    CallContext.FreeNamedDataSlot("OperationId" );
}

void DoSomeStepOfOperation()
{
    // Tu wykonywane jest jakieś rejestrowanie.
    Trace.WriteLine("W operacji: " +
        CallContext.LogicalGetData("OperationId" ));
}

---

