如何在TPL C#中将Task返回值分配给某些变量

时间:2019-02-20 17:40:37

标签: c# asp.net-core task-parallel-library

这是我的C#函数

public async Task GetAttendance(IEnumerable<Zone> zones)
{
    try
    {
        foreach (var zone in zones)
        {
            var req = new AttendeeRequestTO(zone.StartTime, zone.EndTime, zone.ZoneId.ToString(), accessToken);

            //THROWING COMPILE TIME ERROR
            zone.AttendanceCount = Task.Factory.StartNew(() => _vClient.GetAttendeesCount(req));
        }
    }
    catch (Exception ex)
    {
    }
}

错误

  

错误CS0029无法将类型'System.Threading.Tasks.Task>'隐式转换为'int?'

我不想为每个任务申请等待时间,因为每个任务都是独立的,并且我希望每个任务都可以在自己的上下文中运行而无需等待任何其他任务。

我的意思是
 任务T1-转到API,获取值并设置计数
 任务T2-转到API,获取值并设置计数
 任务T3-转到API,获取值并设置计数

T2不应该等待T1完成,T3不应该等待T2完成等等。

如何将每个任务的输出值分配给zone.AttendanceCount

2 个答案:

答案 0 :(得分:4)

进行异步并发的方法是使用await调用每个异步方法 ,然后使用await Task.WhenAll

由于您有一个集合,并且每个集合都需要一个任务,因此可以使用LINQ调用每个异步方法:

var tasks = zones.Select(async zone =>
{
  var req = new AttendeeRequestTO(zone.StartTime, zone.EndTime, zone.ZoneId.ToString(), accessToken);
  zone.AttendanceCount = await Task.Run(() => _vClient.GetAttendeesCount(req));
}).ToList();
await Task.WhenAll(tasks);

请注意,我也是changed StartNew to Run

如果可能的话,最好在客户端上使用GetAttendeesCountAsync方法(假设它正在进行I / O调用)。如果该方法可用,则可以避免不必要地使用线程池:

var tasks = zones.Select(async zone =>
{
  var req = new AttendeeRequestTO(zone.StartTime, zone.EndTime, zone.ZoneId.ToString(), accessToken);
  zone.AttendanceCount = await _vClient.GetAttendeesCountAsync(req);
}).ToList();
await Task.WhenAll(tasks);

答案 1 :(得分:0)

Task.Factory.StartNew返回一个Task或Task ,因此,如果要获取异步操作返回的结果,则应等待它。

您只需要添加等待:

zone.AttendanceCount = await Task.Factory.StartNew(() => _vClient.GetAttendeesCount(req));

还请注意,建议使用Task.Run代替Task.Factory.StartNew。