【问题标题】:how to assign Task return value to some variable in TPL C#如何将Task返回值分配给TPL C#中的某个变量
【发布时间】:2019-02-20 17:40:37
【问题描述】:

这是我的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?”

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

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

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

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

【问题讨论】:

  • 您需要提供有关您的问题的更多信息,您得到的错误是什么? AttendanceCount 的类型是什么?
  • 如果你真的需要为此使用单独的任务(线程),你可以有一个区域变量的列表,当你遍历循环时,你以异步/等待风格为每个变量分配值..
  • @ZackISSOIR。添加了错误详情
  • 如果您的代码不是异步的,为什么还要使用async
  • 你的await在哪里?您还可以附上完整的异常消息吗?有一个“>”,我假设您已经从 System.Threading.Tasks.Task&lt;int&gt; 修剪了数据类型

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


【解决方案1】:

做异步并发的方法是调用每个异步方法使用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);

【讨论】:

【解决方案2】:

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

你只需要添加等待:

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

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

【讨论】:

猜你喜欢
  • 2021-03-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-01-07
相关资源
最近更新 更多