有没有办法发信号通知System.Threading.Tasks.Task?

时间:2012-11-21 15:00:57

标签: c# .net

我有一个库,它是许多网络连接的复杂仲裁者。它的主要对象的每个方法都有一个委托,当网络响应给定的请求时会调用该委托。

我想翻译我的库以使用新的.NET 4.5“async / await”模式;这将要求我返回一个“任务”对象,该对象将向用户发出呼叫的异步部分已完成的信号。创建这个对象需要一个代表任务的函数 - 据我所知,它本质上是一个轻量级的线程。

这并不适合我的库的设计 - 我希望任务的行为更像是一个事件,并直接向用户发出他们的请求已经完成的信号,而不是代表一个函数。这可能吗?我应该避免以这种方式滥用“异步/等待”模式吗?

我不知道我的措辞是否很好,我希望你理解我的意思。谢谢你的帮助。

2 个答案:

答案 0 :(得分:7)

  

据我所知,它本质上是一个轻量级的线程。

不,那不是真的。在某些情况下,我可以是真的,但这只是Task的一种用法。你可以通过传递一个委托来启动一个线程,让它执行它(通常是异步的,可能是同步的,默认情况下使用线程池)。

使用线程的另一种方法是使用TaskCompletionSource。当您这样做时,任务(可能)不会创建任何线程,使用线程池或沿着这些线的任何东西。此模型的一个常见用法是将基于事件的API转换为基于任务的API:

让我们假设,仅仅因为它是一个常见的例子,我们希望在我们拥有的Task关闭时完成From。事件发生时,已发生FormClosed事件:

public static Task WhenClosed(this Form form)
{
    var tcs = new TaskCompletionSource<object>();

    form.FormClosing += (_, args) =>
    {
        tcs.SetResult(null);
    };

    return tcs.Task;
}

我们创建一个TaskCompletionSource,为相关事件添加一个处理程序,在该处理程序中我们发出任务完成信号,TaskCompletionSource为我们提供了Task返回给来电者。这个Task不会导致创建任何新线程,它不会使用线程池或类似的东西。

你可以使用这个看起来非常异步的构造的基于任务/事件的模型,但只使用一个线程来完成所有的工作(UI线程)。

一般情况下,只要您希望Task表示除执行函数以外的其他内容,您需要使用TaskCompletionSource进行考虑。除了可能使用现有的TPL方法之外,它通常是解决问题的合适概念方法,例如WhenAllWhenAny等。

  

我应该避免以这种方式滥用“异步/等待”模式吗?

不,因为它不是滥用。这是Task构造以及async/await的完美选择。例如,考虑一下您可以使用上面的辅助方法编写的代码:

private async void button1_Click(object sender, EventArgs e)
{
    Form2 popup = new Form2();
    this.Hide();
    popup.Show();
    await popup.WhenClosed();
    this.Show();
}

此代码现在就像读取一样;创建一个新表单,隐藏自己,显示弹出窗口,等待弹出窗口关闭,然后再次显示自己。但是,由于它不是阻塞等待,因此UI线程不会被阻止。我们也不需要为事件烦恼;添加处理程序,处理多个上下文;移动我们的逻辑或任何一个。 (所有这一切都发生了,它只是隐藏在我们身上。)

答案 1 :(得分:4)

  

我想翻译我的库以使用新的.NET 4.5“async / await”模式;这将要求我返回一个“任务”对象,该对象将向用户发出呼叫的异步部分已完成的信号。

嗯,不是真的 - 你可以返回任何实现等待模式的东西 - 但Task是最简单的方法。

  

这并不适合我的库的设计 - 我希望任务的行为更像是一个事件,并直接向用户发出他们的请求已经完成的信号,而不是代表一个函数。

您可以调用Task.ContinueWith作为“处理程序”,以便在任务完成时执行。实际上,这就是TaskAwaiter所做的事情。

说实话,你的问题并不十分清楚,但是如果你真的想创建一个Task,你可以随时强制完成,我怀疑你只是想要TaskCompletionSource<TResult> - 您调用SetResultSetCanceledSetException方法来指示相应的完成类型。 (或者您可以调用TrySet...版本。)使用Task属性将任务返回到任何需要它。