【问题标题】:Can I await something if there's no GetAwaiter method?如果没有 GetAwaiter 方法,我可以等待吗?
【发布时间】:2014-09-25 19:41:22
【问题描述】:

我看到一些关于设计自定义等待类型的文章:

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

现在考虑下面的例子:

<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" />

和:

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");
}

如果没有GetAwaiter()方法,为什么我可以await IObservable&lt;T&gt;(在这种情况下订阅完成时)?

它是由编译器实现的吗?是否有可能实现await 无需显式此方法的东西(某些场景正在使用哪些接口)? 为什么没有类似的东西:

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

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

... 还是真正的接口来创建自定义的可等待对象?

【问题讨论】:

  • 如果您正在阅读有关该主题的书籍,它对此事有何看法?它不解释它自己的例子吗?
  • 算了,我错过了“那个GetAwait方法可以是一个扩展方法..”的部分。

标签: c# .net async-await system.reactive


【解决方案1】:

首先,

你不能 await something 没有 GetAwaiter 方法返回 somethingGetResult, OnCompleted, @987654325 @ 并实现INotifyCompletion

那么,你怎么能awaitIObservable&lt;T&gt;

除了实例方法之外,编译器还接受GetAwaiter 扩展方法。在这种情况下,Reactive Extensions 的 Observable 提供了该扩展:

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

例如,这就是我们如何使字符串可等待(编译但显然不会实际工作):

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";

【讨论】:

    【解决方案2】:

    如果不存在,您可以通过扩展方法提供自己的 GetAwaiter 实现。

    http://blogs.msdn.com/b/pfxteam/archive/2011/01/13/10115642.aspx

    【讨论】:

      猜你喜欢
      • 2016-02-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-10-26
      • 1970-01-01
      • 2019-03-27
      • 2020-10-06
      相关资源
      最近更新 更多