任务的事件 - 寻找优雅的方式

时间:2017-06-26 17:12:25

标签: c# events task extension-methods c#-7.0

简介

在我的代码中,有很多地方我需要等到事件发生后再继续。任务(与await结合使用)对此非常理想,因此我认为我会为EventHandler<T>制作一种可以简化此类情况的扩展方法。

我需要像这样的伪代码:

event EventHandler<int> AllFinished;

async Task<int> DoThings()
{
    InitiateAnAction();
    var n = await /* wait for AllFinished to fire */;
    return n;
}

尝试#1

我的第一个想法是,我实施了从EventHandlerTask的明确演员,但我发现operators cannot be overloaded with extension methods。如果它有效,它将看起来像这样:

var n = await (Task)AllFinished;

尝试#2

我的第二次尝试是使用普通的扩展方法。这是我使用的代码:

public static Task<(object sender, T args)> Once<T>(this EventHandler<T> e)
{
    var tcs = new TaskCompletionSource<(object, T)>();
    EventHandler<T> d = null;

    d = delegate (object sender, T args)
    {
        tcs.SetResult( (sender, args) );
        e -= d;
    };

    e += d;
    return tcs.Task;
}

但是我发现了events can't be passed as arguments,因此e += de -= d没有做任何事情(他们甚至没有发出错误)。如果它有效,它就会像这样使用:

var (sender, number) = await AllFinished.Once();

问题

有没有优雅的等待事件的方式?我之前的两次尝试中,我更喜欢单线:

var n = await (Task)AllFinished;
var (sender, number) = await AllFinished.Once();

如果可能,请避免将事件的名称作为字符串传递。这种方法使得无法使用IntelliSense重命名功能,当我忘记它时可能会破坏我的代码。

为什么我需要这个?

如果您认为等待方法中的事件是设计不良的结果,您可以深入我的original Cef-related question并在那里发布更好的解决方案。

0 个答案:

没有答案