Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

I saw some articles about designing a custom awaitable type:

http://books.google.com.br/books?id=1On1glEbTfIC&pg=PA83&lpg=PA83&dq=create+a+custom+awaitable+type

Now consider the example below:

<Button x:Name="BtnA"
        Width="75"
        Margin="171,128,0,0"
        HorizontalAlignment="Left"
        VerticalAlignment="Top"
        Click="BtnA_Click"
        Content="Button A" />
<Button x:Name="BtnB"
        Width="75"
        Margin="273,128,0,0"
        HorizontalAlignment="Left"
        VerticalAlignment="Top"
        Content="Button B"  Click="BtnB_OnClick" />

and:

private async void BtnA_Click(object sender, RoutedEventArgs e)
{
    MessageBox.Show("Awaiting Button B..");

    var sx = Observable.FromEvent<MouseButtonEventHandler, 
                                  MouseButtonEventArgs>(a => (b, c) => a(c),
                                  add => BtnB.PreviewMouseDown += add,
                                  rem => BtnB.PreviewMouseDown -= rem)
       .Do(a => a.Handled = true)
       .Take(1);

    await sx;

    MessageBox.Show("Button B Pressed after Button A");
}

private void BtnB_OnClick(object sender, RoutedEventArgs e)
{
    MessageBox.Show("Button B Pressed Without Click in Button A");
}

Why can I await IObservable<T> (in this case when subscription is completed), if there's no GetAwaiter() method?

Is it implemented by the compiler? Is it possible to implement something that can await without to explicit this method (some scenarios which interfaces is being used)? And why isn't there something like:

public interface ITask<out T>
{
    IAwaiter<T> GetAwaiter();
}

public interface IAwaiter<out T> : ICriticalNotifyCompletion
{
    bool IsCompleted { get; }
    T GetResult();
}

... or real interfaces to create a custom awaitable?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
390 views
Welcome To Ask or Share your Answers For Others

1 Answer

First of all, no.

You can't await something that doesn't have a GetAwaiter method that returns something that has GetResult, OnCompleted, IsCompleted and implements INotifyCompletion.

So, how are you able to await an IObservable<T>?

The compiler, on top of instance methods, also accepts GetAwaiter extensions methods. In this case Reactive Extensions's Observable provides that extension:

public static AsyncSubject<TSource> GetAwaiter<TSource>(this IObservable<TSource> source);

For example, this is how we can make strings awaitable (which compiles but obviously won't actually work):

public static Awaiter GetAwaiter(this string s)
{
    throw new NotImplementedException();
}
public abstract class Awaiter : INotifyCompletion
{
    public abstract bool IsCompleted { get; }
    public abstract void GetResult();
    public abstract void OnCompleted(Action continuation);
}

await "bar";

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share

548k questions

547k answers

4 comments

86.3k users

...