首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >从异步调用收集响应时使用的数据结构

从异步调用收集响应时使用的数据结构
EN

Stack Overflow用户
提问于 2018-11-17 18:09:16
回答 1查看 65关注 0票数 1

我正在我的应用程序中运行这段代码。

代码语言:javascript
复制
public Task<BulkResponse<JObject>> GetRelatedObjectsAsync(IEnumerable<PrimaryObjectInfo> primaryObjectInfos)
{
    var allSecondaries = new List<Tuple<int, List<JObject>>>();
    var exceptionsDict = new ConcurrentDictionary<int, Exception>();

    var relatedObjectsTasks = primaryObjectInfos.Select(async primaryObjectInfo =>
    {
        try
        {
            var secondaryObject = await objectManager.GetRelatedObjectsAsync(primaryObjectInfo);
            allSecondaries.Add(Tuple.Create(primaryObjectInfo.Index, secondaryObject.ToList()));
        }
        catch (Exception ex)
        {
            exceptionsDict.TryAdd(primaryObjectInfo.Index,  ex);
        }
    });

    await Task.WhenAll(relatedObjectsTasks);

    return ConvertToBulkResponse(allSecondaries, exceptionsDict);
}

当我运行这个代码时,allSecondaries对象有时返回有效的结果列表,有时代码会捕获每个primaryObjectInfo的并行线程的异常。

异步方法objectManager.GetRelatedObjectsAsync()内部调用4-5异步函数,有些函数通过引用传递参数。(参考关键词)

问题:是否使用正确的数据结构来合并所有并行线程的结果?如果是的话,我每次得到不同结果的原因是什么?

EN

回答 1

Stack Overflow用户

发布于 2018-11-17 23:28:53

您最好将执行与结果收集分开:

代码语言:javascript
复制
public Task<BulkResponse<JObject>> GetRelatedObjectsAsync(
    IEnumerable<PrimaryObjectInfo> primaryObjectInfos)
{
    var relatedObjectsTasks = primaryObjectInfos
        .Select(
            async primaryObjectInfo =>
                (primaryObjectInfo.Index,
                 await objectManager.GetRelatedObjectsAsync(primaryObjectInfo)))
        .ToList();

    try
    {
        await Task.WhenAll(relatedObjectsTasks);
    }
    catch
    {
        // observe each task's, exception
    }

    var allSecondaries = new List<(int index, List<JObject> related)>();
    var exceptionsDict = new Dictionary<int, Exception>();

    foreach (var relatedObjectsTask in relatedObjectsTasks)
    {
        try
        {
            allSecondaries.Add(relatedObjectsTask.Result);
        }
        catch (Exception ex)
        {
            exceptionsDict.Add(relatedObjectsTask.index,  ex);
        }
    }

    return ConvertToBulkResponse(allSecondaries, exceptionsDict);
}

您可以查看每个任务的IsFaulted/ExceptionIsCancelled属性,而不是引发异常:

代码语言:javascript
复制
    foreach (var relatedObjectsTask in relatedObjectsTasks)
    {
        if (relatedObjectsTask.IsCancelled)
        {
            exceptionsDict.Add(
                relatedObjectsTask.index,
                new TaskCancelledException(relatedObjectsTask));
        }
        else if (relatedObjectsTask.IsFaulted)
        {
            exceptionsDict.TryAdd(relatedObjectsTask.index,  ex);
        }
        else
        {
            allSecondaries.Add(relatedObjectsTask.Result);
        }
    }
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/53354091

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档