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

Kgn*_*web 0 c# task-parallel-library asp.net-core

这是我的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)
    {
    }
}
Run Code Online (Sandbox Code Playgroud)

错误

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

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

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

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

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

Ste*_*ary 5

实现异步并发的方式是使用调用每个异步方法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);
Run Code Online (Sandbox Code Playgroud)

请注意,我也更改StartNewRun.

如果可能,最好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);
Run Code Online (Sandbox Code Playgroud)

  • 伟大的。我刚刚找到了你的博客 https://blog.stephencleary.com/2013/08/startnew-is-dangerous.html (2认同)