平行WhenAll执行任务时任务缓存 [英] Task caching when performing Tasks in parallel with WhenAll

查看:120
本文介绍了平行WhenAll执行任务时任务缓存的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

  //没有包装的任务,它是异步
VAR activityList =等待dataService.GetActivitiesAsync();

//选择好足够的元组
VAR的结果=(从activityList
活性选择新{
活性=活动,
AthleteTask = DataService的。 GetAthleteAsync(activity.AthleteID)
})了ToList()。 //开始枚举

//等待他们完成,即放弃线程
控制等待Task.WhenAll(results.Select(T => t.AthleteTask));

//设置运动员
的foreach(VAR一对结果)
{
pair.Activity.Athlete = pair.AthleteTask.Result;
}



所以,我下载的运动员数据每个给定的活动。但是这可能是因为我们正在请求同一运动员几次。
如何才能确保GetAthleteAsync方法只会去网上获取的实际数据,如果它没有在我们的记忆缓存?



目前我尝试使用 ConcurrentDictionary< INT,痤疮各类> 的GetAthleteAsync方法中

 专用异步任务< ;运动员GT; GetAthleteAsync(INT athleteID)
{
如果(cacheAthletes.Contains(athleteID))
返回cacheAthletes [atheleID]

**从网页
}
,否则取


解决方案

您可以更改 ConcurrentDictionary 缓存任务<运动员GT; ,而不仅仅是运动员。记住,任务< T> 是一个承诺 - 一个操作,最终将导致 T 。所以,你可以缓存的操作的代替的结果



  ConcurrentDictionary< INT,任务<运动员GT;> cacheAthletes; 



那么,你的逻辑将是这样的:如果操作已经在缓存中,返回缓存任务会立即(同步)。如果不是,则开始下载,添加下载操作到缓存中,并返回新的下载操作。请注意,所有的下载操作的逻辑移动到另一种方法:

 私人任务<运动员GT; GetAthleteAsync(INT athleteID)
{
返回cacheAthletes.GetOrAdd(athleteID,ID => LoadAthleteAsync(ID));
}

私人异步任务<运动员GT; LoadAthleteAsync(INT athleteID)

{
//从网页
负载}

这样,对于相同的运动员将获得相同的任务<多个并行的请求;运动员方式> ,每个运动员只能下载一次


So I have this small code block that will perform several Tasks in parallel.

// 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;
}

So I'm downloading Athlete data for each given Activity. But it could be that we are requesting the same athlete several times. How can we ensure that the GetAthleteAsync method will only go online to fetch the actual data if it's not yet in our memory cache?

Currently I tried using a ConcurrentDictionary<int, Athelete> inside the GetAthleteAsync method

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

       ** else fetch from web
}

解决方案

You can change your ConcurrentDictionary to cache the Task<Athlete> instead of just the Athlete. Remember, a Task<T> is a promise - an operation that will eventually result in a T. So, you can cache operations instead of results.

ConcurrentDictionary<int, Task<Athlete>> cacheAthletes;

Then, your logic will go like this: if the operation is already in the cache, return the cached task immediately (synchronously). If it's not, then start the download, add the download operation to the cache, and return the new download operation. Note that all the "download operation" logic is moved to another method:

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

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

This way, multiple parallel requests for the same athlete will get the same Task<Athlete>, and each athlete is only downloaded once.

这篇关于平行WhenAll执行任务时任务缓存的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆