我编写了一个函数,它将使用相对较新的async / await模式在线程上运行任何函数,并稍后通过可选的回调方法通知调用者。该功能非常简单,如下所示:
private async void DoOperationAsync<T>(Func<T> operation, Action<T> resultAction = null)
{
if (operation == null)
throw new ArgumentNullException("operation");
var result = await Task<T>.Factory.StartNew(operation);
// Notify someone that this finished
if (resultAction != null)
resultAction(result);
}
这对于返回值的函数非常有效。它不适用于返回void的函数(或者我可能不够聪明,无法使其工作)。我可以编写一个不承担返回类型的特殊情况。但是,我想知道一些C#泛型专家是否可以在这种情况下指出一种处理void的方法。是否有工作方式不涉及无效功能的特殊情况?
答案 0 :(得分:5)
我的博客上有async
/await
intro,您可能会觉得有帮助。
我编写了一个函数,使用相对较新的async / await模式运行线程上的任何函数,稍后通过可选的回调方法通知调用者。
这就是Task.Run
的用途。
我确实希望该方法在调用线程上运行(在我的例子中,它通常是我的应用程序的主要UI线程)。
await
已经做到了。
所以,不要像这样编写代码:
DoOperationAsync(() =>
{
// Code that runs on threadpool thread.
return 13;
},
result =>
{
// Code that runs on UI thread.
MessageBox.Show(result.ToString());
});
这样做:
var result = await Task.Run(() =>
{
// Code that runs on threadpool thread.
return 13;
});
// Code that runs on UI thread.
MessageBox.Show(result.ToString());
P.S。 Task.Run
已经具有处理带有和不带返回值的委托的所有必要重载。
答案 1 :(得分:1)
对于无效的async
方法,请使用Task
答案 2 :(得分:0)
尝试使用非通用版本的方法,在执行回调之前等待非通用任务
private async void DoOperationAsync(Func operation, Action resultAction = null)
{
if (operation == null)
throw new ArgumentNullException("operation");
await Task.Factory.StartNew(operation);
// Notify someone that this finished
if (resultAction != null)
resultAction();
}
答案 3 :(得分:0)
你应该避免包裹Task<T>.Factory.StartNew
。请直接使用它,并在可能的情况下尽量使用Task.Run
,在答案中为@StephenCleary advises。
尽管如此,我认为你的问题仍然适用于其他一些模式。如果您不想实现该方法的泛型和非泛型版本,则可以使用伪Empty
结构作为泛型参数。例如,TPL中有TaskCompletionSource<T>
类和Task.FromResult<T>
方法类型,它们没有非泛型版本。如果您不想泄露信息,代码可能类似于:
public struct Empty {
public static Empty Value {
get { return default(Empty); }
}
static Task GetCompletedTask() {
return Task.FromResult(Empty.Value); }
您可以将任何void
方法转换为Empty
func:
static Func<Empty> Func(Action action) {
return () => { action(); return Empty.Value; };
}
DoOperationAsync(Func(() =>
Console.WriteLine("Hello, World!")));
这可以使它与现有的泛型方法一起使用,而不会将任何结果泄露给调用者。