首页 > 解决方案 > 等待多个独立任务的最佳方法/实践是什么?

问题描述

var contractSchemaTask = contractSchemaRepository.GetByContractIdAsync(data.Id);
var sectionsTask = sectionRepository.GetAllByContractIdAsync(id);
var latestContractIdTask = contractRepository
    .GetLatestContractIdByFolderIdAsync(data.FolderId.Value);
List<Task> allTasks = new List<Task>()
    { contractSchemaTask, sectionsTask, latestContractIdTask };
while (allTasks.Any())
{
    Task finished = await Task.WhenAny(allTasks);
    if (finished == contractSchemaTask)
    {
        var contractSchema = await contractSchemaTask;
        result.ReturnData.IsSchedules = contractSchema.Count > 0 ? true : false;
    }
    else if (finished == sectionsTask)
    {
        List<Section> sections = await sectionsTask;

        List<TextValueVM> SectionTabList = sections.Count > 0 ? sections
            .OrderBy(a => a.SectionNumber)
            .Select(a => new TextValueVM()
                { Text = a.ToString(), Value = a.Id.ToString() })
            .ToList() : new List<TextValueVM>();

        bool IsSectionsLinked = false;
        int linkSectionCount = sections
            .Where(x => x.LinkSectionId != null && x.LinkSectionId != Guid.Empty)
            .ToList()
            .Count();
        if (linkSectionCount == 0 && sections.Count > 0)
        {
            List<Guid> sectionIds = sections.Select(x => x.Id.Value).ToList();
            List<Section> currentContractLinkSections = await sectionRepository
                .GetSectionsByLinkSectionIdAsync(sectionIds);
            if (currentContractLinkSections.Count > 0)
            {
                IsSectionsLinked = true;
            }
        }
        else if (linkSectionCount > 0)
        {
            IsSectionsLinked = true;
        }
        result.ReturnData.SectionTabList = SectionTabList;
        result.ReturnData.IsSectionsLinked = IsSectionsLinked;
    }
    else if (finished == latestContractIdTask)
    {
        Guid LatestContractId = await latestContractIdTask;
        result.ReturnData.isLatestContract
            = (data.Id == LatestContractId) ? true : false;
    }
    allTasks.Remove(finished);
}

我正在开发一个 asp.net core 3.0 WebAPI 项目。以上是我使用 while 循环处理的独立任务的示例代码。在异步编程中处理独立任务是否有更好或更有效的方法?

PS:所有 3 个任务都是独立的,它们的响应时间可能会根据从数据库中获取的记录数而有所不同。

标签: c#async-awaitasp.net-core-webapi

解决方案


你应该这样做:

public Task Main()
{
    var result = new Result();
    return Task.WhenAll(TaskOne(result), TaskTwo(result), TaskThree(result));
}

    private async Task TaskOne(Result result)
    {
        var contractSchema = await contractSchemaRepository.GetByContractIdAsync(data.Id);
        //your logic for task1, set related result properties
    }

    private async Task TaskTwo(Result result)
    {
        var sections = await sectionRepository.GetAllByContractIdAsync(id);
        //your logic for task2, set related result properties
    }

    private async Task TaskThree(Result result)
    {
        var latestContractId = await contractRepository.GetLatestContractIdByFolderIdAsync(data.FolderId.Value);
        //your logic for Task3, set related result properties
    }

Result类应该实现为线程安全的,因为任务可以同时执行。如果您只是在每种方法中设置不同的属性,那应该没问题。


推荐阅读