c# - 与 WhenAll 并行执行任务时的任务缓存

标签 c# windows-phone-8 winrt-async

所以我有这个小代码块可以并行执行多个任务。

// no wrapping in Task, it is async
var activityList = await dataService.GetActivitiesAsync();

// Select a good enough tuple
var results = (from activity in activityList
               select new { 
                Activity = activity, 
                AthleteTask = dataService.GetAthleteAsync(activity.AthleteID)
               }).ToList(); // begin enumeration

// Wait for them to finish, ie relinquish control of the thread
await Task.WhenAll(results.Select(t => t.AthleteTask));

// Set the athletes
foreach(var pair in results)
{
  pair.Activity.Athlete = pair.AthleteTask.Result;
}

所以我正在为每个给定的事件下载运动员数据。但也可能是我们多次要求同一个运动员。 我们如何确保 GetAthleteAsync 方法只会联机获取尚未在我们的内存缓存中的实际数据?

目前我尝试使用 ConcurrentDictionary<int, Athelete>在 GetAthleteAsync 方法中

private async Task<Athlete> GetAthleteAsync(int athleteID)
{
       if(cacheAthletes.Contains(athleteID))
             return cacheAthletes[atheleID];

       ** else fetch from web
}

最佳答案

您可以更改您的 ConcurrentDictionary缓存 Task<Athlete>而不仅仅是 Athlete .请记住,一个 Task<T>是一个 promise - 一个最终会导致 T 的操作.因此,您可以缓存操作而不是结果

ConcurrentDictionary<int, Task<Athlete>> cacheAthletes;

然后,您的逻辑将是这样的:如果操作已经在缓存中,则立即(同步)返回缓存的任务。如果不是,则开始下载,将下载操作添加到缓存中,并返回新的下载操作。注意,所有的“下载操作”逻辑都移到了另一个方法中:

private Task<Athlete> GetAthleteAsync(int athleteID)
{
  return cacheAthletes.GetOrAdd(athleteID, id => LoadAthleteAsync(id));
}

private async Task<Athlete> LoadAthleteAsync(int athleteID)
{
  // Load from web
}

这样,对同一个运动员的多个并行请求将得到相同的 Task<Athlete> , 每个运动员只下载一次。

关于c# - 与 WhenAll 并行执行任务时的任务缓存,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25507059/

相关文章:

windows-phone-8 - 适用于 Windows Phone 的 Google Analytics UTM 跟踪

multithreading - 为什么线程池工作项在UI线程上执行?

C# 如何使用标准值初始化包含 list<T> 的对象

c# - 如果 wpf 应用程序没有响应,则自动重启

c# - 入口后面带有 Azure OAuth 的 ASP.NET Core MVC 进入无限登录循环

windows-runtime - Metro App FileIO.WriteTextAsync 多线程

windows-8 - 我们如何知道 SymmetricAlgorithmNames::AesCbc 在 WinRT 中是 128 位还是 256 位?

重复列表条目的 C# 问题

c# - 在项目之间共享对象和信息

c# - 发送一个短信号到固定频率的音频插孔