繁体   English   中英

返回任务而不是任务 <TResult> 来自TaskCompletionSource

[英]Return Task instead of Task<TResult> from TaskCompletionSource

正如我在几个编码示例中看到的,以及从这个SO问题我可以理解的,我应该能够从TaskCompletionSource返回一个非泛型任务

(i.e., Return Task and not Task<TResult> from the method UploadFilesAsync) 

但是以下代码:

public async Task UploadFilesAsync(string fileAPath, string fileBPath)
{
   var tcs = new TaskCompletionSource<Object>();

   //logic to process files

   try
   {
      await Task.WhenAll(uploadFileAAsync(fileAPath), 
                         uploadFileBAsync(fileBPath));
      tcs.TrySetResult(null);
   }
   catch (Exception e)
   {
      tcs.SetException(e);
   }
   finally
   {
      //logic to clean up files
   }
   return tcs.Task;
}

产生以下语法错误

'UploadFilesAsync(string, string)' is an async method that returns 'Task', 
a return keyword must not be followed by an object expression. 
Did you intend to return 'Task<T>'?

我的目标是.NET 4.5。 我知道它可以返回Task(对象),但这会使API感觉“脏”。 是首选返回Task(对象)还是可以返回Task(非泛型,如代码所示)?

我知道它可以工作返回Task(对象)

那么,这不会达到你的预期。

麻烦的是你正在尝试返回一个任务......而异步方法会自动将返回值包装在另一个任务中。 说实话,目前还不清楚为什么你在这里使用异步方法。 为什么不写这个:

public Task UploadFilesAsync(string fileAPath, string fileBPath)
{
    return Task.WhenAll(uploadFileAAsync(fileAPath), uploadFileBAsync(fileBPath));
}

那不是你想做的吗? 你只想要一个在两个“子操作”完成时完成的任务,对吧? 这正是Task.WhenAll返回的内容。 您的方法仍然是非阻塞的 - 它不会等到操作完成后再返回。 只是你正在使用Task.WhenAll是非阻塞的事实来实现它,而不是异步方法。

编辑:请注意,如果您想在该方法中执行其他操作,则可以在不使用TaskCompletionSource情况下将其设置为异步方法:

public async Task UploadFilesAsync(string fileAPath, string fileBPath)
{
    // Upload the files
    await Task.WhenAll(uploadFileAAsync(fileAPath), uploadFileBAsync(fileBPath));
    await SomethingElseAsync();
    MaybeDoSomethingCheap();
}

请注意,即使此处的async方法返回Task ,您也没有返回值 - async / await机制为您处理所有这些,返回一个任务,该任务将在MaybeDoSomethingCheap()完成时完成,或者如果异常则返回错误被扔了。

据我所知,在使用TaskCompletionSource<T>时没有直接返回Task对象的方法。

通常我更喜欢在这些情况下返回Task<bool>类型对象。 但你是对的,如果函数的返回值不可用,则返回泛型类型对象是没有意义的。

但实际上你不需要创建一个TaskCompletionSource因为你在函数中有一个await关键字。 TaskCompletionSource通常用于将同步函数转换为异步函数。 由于您已经在调用异步函数(实际上这似乎是唯一的功能),因此您无需创建TaskCompletionSource

public async Task UploadFilesAsync(string fileAPath, string fileBPath)
{
        return await Task.WhenAll(uploadFileAAsync(fileAPath), uploadFileBAsync(fileBPath));
}

暂无
暂无

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

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