如何将任务 return 值分配给 TPL C# 中的某个变量

how to assign Task return value to some variable in TPL C#

这是我的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)
    {
    }
}

错误

Error CS0029 Cannot implicitly convert type 'System.Threading.Tasks.Task>' to 'int?'

我不想为每个任务应用等待,因为每个任务都是独立的,我希望每个任务在其自己的上下文中 运行 而无需等待任何其他任务。

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

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

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

Task.Factory.StartNew returns 一个 Task 或一个 Task 所以如果你想获得异步操作返回的结果你应该等待它。

你只需要添加 await:

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

另请注意,建议使用 Task.Run 而不是 Task.Factory.StartNew。

异步并发的方法是不用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);