C# 非通用 TaskCompletionSource 或替代方案
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11969208/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Non-Generic TaskCompletionSource or alternative
提问by Kevin Kalitowski
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 TaskCompletionSourcebut that class is generic and returns an object like Task<bool>when all I want is a plain Taskwith no return value.
我有这个工作,TaskCompletionSource但那个类是通用的,并返回一个对象,就像Task<bool>我想要的只是一个Task没有返回值的普通对象。
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.Closedevent fires? I understand that I could just ignore the boolthat is being returned in this code. I am looking for a different solution than that.
如何返回一个功能类似的非通用任务,我可以等待直到dialogParameters.Closed事件触发?我知道我可以忽略bool此代码中返回的内容。我正在寻找与此不同的解决方案。
采纳答案by Kevin Kalitowski
The method can be changed to:
该方法可以更改为:
public Task ShowAlert(object message, string windowTitle)
Task<bool>inherits from Taskso you can return Task<bool>while only exposing Taskto 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>. 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)
TaskCompletionSource<TResult> 没有非通用的对应物。但是,Task<TResult> 派生自 Task,因此泛型 TaskCompletionSource<TResult> 可用于 I/O 绑定方法,这些方法通过利用带有虚拟 TResult 的源来简单地返回 Task(布尔值是一个很好的默认选择,并且如果开发人员担心 Task 的使用者将其向下转换为 Task<TResult>,则可以使用私有 TResult 类型)
回答by Stephen Cleary
If you don't want to leak information, the common approach is to use TaskCompletionSource<object>and complete with a result of null. Then just return it as a Task.
如果你不希望泄露的信息,常见的方法是使用TaskCompletionSource<object>和完成的结果null。然后将其作为Task.
回答by georgiosd
Nito.AsyncEximplements a non-generic TaskCompletionSourceclass, credit to Mr @StephenCleary above.
Nito.AsyncEx实现了一个非泛型TaskCompletionSource类,归功于上面的 @StephenCleary 先生。
回答by Melbourne Developer
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. This is the example:
本文档中有一个示例,我认为它可以解决 Kevin 指出的问题。这是示例:
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. But, if you change the method slightly, the method will compile with async/await:
一开始我觉得这不好,因为你不能在没有编译消息的情况下直接将“async”修饰符添加到方法中。但是,如果您稍微更改该方法,该方法将使用 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;. So, I still believe that this is a serious design flaw in the async/await c# syntax.
编辑:起初我以为我已经克服了困难。但是,当我在我的应用程序中运行等效代码时,这段代码只会让应用程序在等待 tcs.Task; 时挂起。所以,我仍然认为这是 async/await c# 语法中的一个严重的设计缺陷。

