编程语言
首页 > 编程语言> > C#-启动后台任务并立即返回

C#-启动后台任务并立即返回

作者:互联网

我有一个名为DownloadFileAsync(url,Func< RemoteFileResponse,Task> onDownloadFinished)的方法,该方法执行以下操作:

>检查缓存,如果找到,立即返回缓存并启动后台任务以查看是否需要更新缓存
>如果未找到,则返回null并启动后台任务以异步下载文件
>下载文件后,它将调用onDownloadFinished处理程序.

这对我来说很脏,因为我需要在后台线程上执行下载,但我等不及了,因为我希望能够立即返回缓存的文件.问题是如果执行此操作,将会丢失任何异常上下文.

我能想到的一些选择:

>使用IProgress界面报告缓存文件,然后在下载完成后报告下载结果.
>将方法分为两个调用(一个用于获取缓存的文件),另一个调用以下载/更新(这不是首选方法,因为我想保持接口与一个方法的连接).

想知道是否有人对我该如何做有其他建议?

我的方法的伪代码:

Task<IFile> async DownloadFileAsync(url, Func<RemoteFileResponse, Task> onDownloadFinished)
{
   var cache = await CheckCacheAsync(url);

   // don't await this so the callee can use the cached file right away 
   // instead return the download result on the download finished callback
   DownloadUrlAndUpdateCache(url, onDownloadFinished);

   return cache
}

解决方法:

如果您的缓存是内存中缓存,那么缓存任务而不是结果更容易:

ConcurrentDictionary<Url, Task<IFile>> cache = ...;

Task<IFile> DownloadFileAsync(url) // no async keyword
{
  return cache.GetOrAdd(url, url => DownloadUrlAsync(url));
}

private async Task<IFile> DownloadUrlAsync(url)
{
  ... // actual download
}

从逻辑上讲,GetOrAdd就是这样做的(但是以线程安全且更有效的方式):

if (cache.ContainsKey(url))
  return cache[url];
cache[url] = DownloadUrlAsync(url);
return cache[url];

但是请注意,这将缓存完整的任务,因此也会缓存下载异常.

标签:asynchronous,async-await,c
来源: https://codeday.me/bug/20191119/2038570.html