简体   繁体   English

非通用 TaskCompletionSource 或替代方案

[英]Non-Generic TaskCompletionSource or alternative

I'm working with an alert window (Telerik WPF) that is normally displayed asynchronously ( code continues running while it is open) and I want to make it synchronous by using async/await.我正在使用通常异步显示的警报窗口 (Telerik WPF)(代码在打开时继续运行),我想通过使用 async/await 使其同步。

I have this working with TaskCompletionSource but that class is generic and returns an object like Task<bool> when all I want is a plain Task with no return value.我有这个与TaskCompletionSource一起工作,但该类是通用的,当我想要的只是一个没有返回值的普通Task时,它返回一个像Task<bool>这样的对象。

public Task<bool> ShowAlert(object message, string windowTitle)
{
    var dialogParameters = new DialogParameters { Content = message };

    var tcs = new TaskCompletionSource<bool>();
    dialogParameters.Closed += (s, e) => tcs.TrySetResult(true);

    RadWindow.Alert(dialogParameters);

    return tcs.Task;
}

The code that calls that method is调用该方法的代码是

await MessageBoxService.ShowAlert("The alert text.")

How can I return a non-generic Task that functions similarly which I can await until the dialogParameters.Closed event fires?如何返回一个功能类似的非通用任务,我可以等待直到dialogParameters.Closed事件触发? I understand that I could just ignore the bool that is being returned in this code.我知道我可以忽略此代码中返回的bool I am looking for a different solution than that.我正在寻找与此不同的解决方案。

The method can be changed to:该方法可以更改为:

public Task ShowAlert(object message, string windowTitle)

Task<bool> inherits from Task so you can return Task<bool> while only exposing Task to the caller Task<bool>继承自Task所以你可以返回Task<bool>而只将Task暴露给调用者

Edit:编辑:

I found a Microsoft document, http://www.microsoft.com/en-us/download/details.aspx?id=19957 , by Stephen Toub titled 'The Task-based Asynchronous pattern' and it has the following excerpt that recommends this same pattern.我找到了一个 Microsoft 文档, http://www.microsoft.com/en-us/download/details.aspx?id= 19957,由 Stephen Toub 撰写,标题为“基于任务的异步模式”,它有以下摘录建议这个相同的模式。

There is no non-generic counterpart to TaskCompletionSource<TResult>. TaskCompletionSource<TResult> 没有非通用的对应物。 However, Task<TResult> derives from Task, and thus the generic TaskCompletionSource<TResult> can be used for I/O-bound methods that simply return a Task by utilizing a source with a dummy TResult (Boolean is a good default choice, and if a developer is concerned about a consumer of the Task downcasting it to a Task<TResult>, a private TResult type may be used)但是,Task<TResult> 派生自 Task,因此泛型 TaskCompletionSource<TResult> 可用于 I/O 绑定方法,这些方法通过利用带有虚拟 TResult 的源来简单地返回 Task(布尔值是一个很好的默认选择,并且如果开发人员担心 Task 的使用者将其向下转换为 Task<TResult>,则可以使用私有 TResult 类型)

If you don't want to leak information, the common approach is to use TaskCompletionSource<object> and complete with a result of null .如果不想泄漏信息,常见的做法是使用TaskCompletionSource<object>并以null的结果完成。 Then just return it as a Task .然后将其作为Task返回。

.NET 5 has a non-generic TaskCompletionSource . .NET 5 有一个非通用的TaskCompletionSource

It was added in this pull request: https://github.com/dotnet/runtime/pull/37452/files#diff-4a72dcb26e2d643c337baef9f64312f3它被添加到这个拉取请求中: https : //github.com/dotnet/runtime/pull/37452/files#diff-4a72dcb26e2d643c337baef9f64312f3

Nito.AsyncEx实现了一个非通用的TaskCompletionSource类,归功于上面的 @StephenCleary 先生。

From @Kevin Kalitowski来自@Kevin Kalitowski

I found a Microsoft document, http://www.microsoft.com/en-us/download/details.aspx?id=19957 , by Stephen Toub titled 'The Task-based Asynchronous pattern'我找到了一个 Microsoft 文档, http://www.microsoft.com/en-us/download/details.aspx?id= 19957,由 Stephen Toub 撰写,标题为“基于任务的异步模式”

There is an example in this document which I think deals with the issue as Kevin points out.本文档中有一个示例,我认为它可以解决 Kevin 指出的问题。 This is the example:这是示例:

public static Task Delay(int millisecondsTimeout)
{
    var tcs = new TaskCompletionSource<bool>();
    new Timer(self =>
    {
        ((IDisposable)self).Dispose();
        tcs.TrySetResult(true);
    }).Change(millisecondsTimeout, -1);
    return tcs.Task;
}

At first I thought it was not good because you can't directly add the "async" modifier to the method without a compilation message.一开始我觉得这不好,因为你不能在没有编译消息的情况下直接将“async”修饰符添加到方法中。 But, if you change the method slightly, the method will compile with async/await:但是,如果您稍微更改该方法,该方法将使用 async/await 进行编译:

public async static Task Delay(int millisecondsTimeout)
{
    var tcs = new TaskCompletionSource<bool>();
    new Timer(self =>
    {
        ((IDisposable)self).Dispose();
        tcs.TrySetResult(true);
    }).Change(millisecondsTimeout, -1);
    await tcs.Task;
}

Edit: at first I thought I'd gotten over the hump.编辑:起初我以为我已经克服了困难。 But, when I ran the equivalent code in my app, this code just makes the app hang when it gets to await tcs.Task;.但是,当我在我的应用程序中运行等效代码时,这段代码只会让应用程序在等待 tcs.Task; 时挂起。 So, I still believe that this is a serious design flaw in the async/await c# syntax.所以,我仍然认为这是 async/await c# 语法中的一个严重的设计缺陷。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM