c# - 如何将await.WhenAny() 与GetAwaiter 扩展方法结合起来

标签 c# async-await extension-methods

我想等待一个button.click()事件。为此创建了一个扩展 GetAwaiter() 方法:

public static class ButtonAwaiterExtensions
{
    public static ButtonAwaiter GetAwaiter(this Button button)
    {
        return new ButtonAwaiter()
        {
            Button = button
        };
    }

    public class ButtonAwaiter : INotifyCompletion
    {
        public bool IsCompleted
        {
            get { return false; }
        }

        public void GetResult()
        {

        }

        public Button? Button { get; set; }

        public void OnCompleted(Action continuation)
        {
            RoutedEventHandler? h = null;
            h = (o, e) =>
            {
                Button!.Click -= h;
                continuation();
            };
            Button!.Click += h;
        }

    }
}

(我在这里找到它:http://blog.roboblob.com/2014/10/23/awaiting-for-that-button-click/)

这样我就可以直接使用 await Button1; 等待 Button1.Click() 事件,这很棒。

但是我不知道如何将这个可等待与诸如 await Task.WhenAny() 之类的东西结合起来

我试过了

await Task.WhenAny(Button1, Button2);

它会告诉我它“无法从按钮转换为任务”。

我想我在这里找到了解决方案: Using `Task.WhenAll` with `INotifyCompletion`只需添加一个方法

public static async Task GetTask()
{
    await this;
}

到我的 ButtonAwaiterExtensions 类,但关键字 this 不能在我的静态类中使用。

我不知道该方法要返回什么,也不知道如何等待任何Button.Click()。有什么想法吗?

最佳答案

感谢 Sebastian Schumann 评论 ( how can I combine await.WhenAny() with GetAwaiter extension method ),我通过直接向 ButtonAwaiterExtensions 类添加另一个扩展方法解决了我的问题:

public async static Task AsTask(this Button self) => await self;

完整的解决方案:

public static class ButtonAwaiterExtensions
{
    public static ButtonAwaiter GetAwaiter(this Button button)
    {
        return new ButtonAwaiter()
        {
            Button = button
        };
    }

    public class ButtonAwaiter : INotifyCompletion
    {
        public bool IsCompleted
        {
            get { return false; }
        }

        public void GetResult()
        {

        }

        public Button? Button { get; set; }

        public void OnCompleted(Action continuation)
        {
            RoutedEventHandler? h = null;
            h = (o, e) =>
            {
                Button!.Click -= h;
                continuation();
            };
            Button!.Click += h;
        }
    }
   public async static Task AsTask(this Button self) => await self;
}

GetAwaiter 的替代(短一点)实现可能是:

public static TaskAwaiter GetAwaiter(this Button self)
{
    ArgumentNullException.ThrowIfNull(self);
    TaskCompletionSource tcs = new();
    self.Click += OnClick;
    return tcs.Task.GetAwaiter();

    void OnClick(object sender, EventArgs args)
    {
        self.Click -= OnClick;
        tcs.SetResult();
    }
}

关于c# - 如何将await.WhenAny() 与GetAwaiter 扩展方法结合起来,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73959407/

相关文章:

javascript - 异步和等待nodejs

c# - 创建一个扩展方法来做周期性的工作

flutter - Dart扩展功能仅在与调用它的文件相同时可见

c# - 反向 RegEx MatchCollection 项目?

c# - .Net 核心服务容器,我能保证为接口(interface)注册最后一个服务吗?

c# - 为什么这段代码无法访问?

linq - 通过扩展方法在 linq to sql 查询中封装逻辑

c# - 获取网络中可用的所有打印机 - 不仅仅是本地打印机

c# - 确定 ForEachAsync 并行度的因素

xamarin - 如何在 DelegateCommand 中使用异步方法