C# 同时执行所有任务并等待其完成?

C# 同时执行所有任务并等待其完成?,c#,.net,asynchronous,async-await,task-parallel-library,C#,.net,Asynchronous,Async Await,Task Parallel Library,我想同时执行一系列异步方法。这些方法中的每一个都返回true或false,以判断它们是否成功执行。他们的结果也记录在我们的审计跟踪中,以便我们能够诊断问题 我的一些函数并不依赖于所有这些方法的成功执行,我们完全希望其中一些方法会不时失败。如果他们真的失败了,程序将继续执行,它只会提醒我们的支持人员他们需要纠正这个问题 我试图找出什么是同时执行所有这些函数的最佳方法,而父函数只有在它们都开始执行之后才等待它们。如果任何函数失败,父函数将返回False,这将提醒我的应用程序停止执行 我的想法是做一些

我想同时执行一系列异步方法。这些方法中的每一个都返回true或false,以判断它们是否成功执行。他们的结果也记录在我们的审计跟踪中,以便我们能够诊断问题

我的一些函数并不依赖于所有这些方法的成功执行,我们完全希望其中一些方法会不时失败。如果他们真的失败了,程序将继续执行,它只会提醒我们的支持人员他们需要纠正这个问题

我试图找出什么是同时执行所有这些函数的最佳方法,而父函数只有在它们都开始执行之后才等待它们。如果任何函数失败,父函数将返回
False
,这将提醒我的应用程序停止执行

我的想法是做一些类似的事情:

public async Task<bool> SetupAccessControl(int objectTypeId, int objectId, int? organizationId)
{
    using (var context = new SupportContext(CustomerId))
    {
        if (organizationId == null)
        {
            var defaultOrganization = context.Organizations.FirstOrDefault(n => n.Default);
            if (defaultOrganization != null)  organizationId = defaultOrganization.Id;
        }
    }

    var acLink = AcLinkObjectToOrganiation(organizationId??0,objectTypeId,objectId);

    var eAdmin = GrantRoleAccessToObject("eAdmin", objectTypeId, objectId);
    var defaultRole = GrantRoleAccessToObject("Default", objectTypeId, objectId);

    await acLink;
    await eAdmin;
    await defaultRole;

    var userAccess = (objectTypeId != (int)ObjectType.User) || await SetupUserAccessControl(objectId);

    return acLink.Result && eAdmin.Result && defaultRole.Result && userAccess;
}

public async Task<bool> SetupUserAccessControl(int objectId)
{
    var everyoneRole = AddToUserRoleBridge("Everyone", objectId);
    var defaultRole = AddToUserRoleBridge("Default", objectId);

    await everyoneRole;
    await defaultRole;

    return everyoneRole.Result && defaultRole.Result;
}
公共异步任务SetupAccessControl(int-objectTypeId、int-objectId、int-organizationId)
{
使用(var-context=new-SupportContext(CustomerId))
{
如果(organizationId==null)
{
var defaultOrganization=context.Organizations.FirstOrDefault(n=>n.Default);
如果(defaultOrganization!=null)organizationId=defaultOrganization.Id;
}
}
var acLink=aclinkobjecttoorganization(organizationId??0,objectTypeId,objectId);
var eAdmin=GrantRoleAccessToObject(“eAdmin”,objectTypeId,objectId);
var defaultRole=GrantRoleAccessToObject(“默认”,objectTypeId,objectId);
等待联系;
等待时机;
等待默认角色;
var userAccess=(objectTypeId!=(int)ObjectType.User)| |等待SetupUserAccessControl(objectId);
返回acLink.Result&&eAdmin.Result&&defaultRole.Result&&userAccess;
}
公共异步任务SetupUserAccessControl(int objectId)
{
var everyoneRole=AddToUserRoleBridge(“每个人”,objectId);
var defaultRole=AddToUserRoleBridge(“默认”,objectId);
等待每一个人;
等待默认角色;
返回everyoneRole.Result&&defaultRole.Result;
}

有更好的选择吗?我应该以任何方式重组吗?我只是想加快执行时间,因为我有一个父函数,它执行将近20个相互独立的函数。即使在速度最慢的情况下,如果没有异步,执行也只需要1-2秒。但是,这将被扩展,最终使父调用执行数百次(批量插入)

异步方法有一个同步部分,即到达未完成任务的第一次等待之前的部分(如果没有,则整个方法同步运行)。该部分使用调用线程同步执行

如果您想同时运行这些方法而不并行化这些部分,只需调用这些方法,收集任务并使用
Task.whalll
一次等待它们。完成所有任务后,您可以检查各个结果:

async Task<bool> SetupUserAccessControlAsync(int objectId)
{
    var everyoneRoleTask = AddToUserRoleBridgeAsync("Everyone", objectId);
    var defaultRoleTask = AddToUserRoleBridgeAsync("Default", objectId);

    await Task.WhenAll(everyoneRoleTask, defaultRoleTask)

    return await everyoneRoleTask && await defaultRoleTask;
}
如果所有方法都返回
bool
,则可以将所有任务收集到一个列表中,从
Task中获取结果。当所有方法返回
时,检查是否所有方法都返回
true

async Task<bool> SetupUserAccessControlAsync(int objectId)
{
    var tasks = new List<Task<bool>>();
    tasks.Add(AddToUserRoleBridgeAsync("Everyone", objectId));
    tasks.Add(AddToUserRoleBridgeAsync("Default", objectId));

    return (await Task.WhenAll(tasks)).All(_ => _);
}
async任务SetupUserAccessControlAsync(int objectId)
{
var tasks=新列表();
添加(AddToUserRoleBridgeAsync(“每个人”,objectId));
添加(AddToUserRoleBridgeAsync(“默认”,objectId));
return(wait Task.WhenAll(tasks)).All(=>;
}

我曾经使用Parallel.Invoke来处理这个问题。您可能想看看
任务。whalll
。对于结果值,如果不知道所涉及的一半类型,很难判断…幸运的是,如果我不需要将值传递给父级(或等待它们在另一个函数中使用),所有函数都将返回真值或假值。我不担心它们完全同时执行,我只是想确保每一个调用都能尽快执行,而不会阻止下一个调用的执行。@Jdsfighter这些句子相互矛盾。如果希望第二个操作尽快启动,则需要第一个操作尽快释放调用线程。这意味着将同步部分卸载到不同的线程中,每个调用都执行一系列数据库功能。我只是想确保我可以快速执行这些功能,而不会长时间阻塞调用线程(就像同步数据库调用一样)。@Jdsfighter如果不使用
Task。Run
调用线程将逐个运行这些同步部分。如果这是一个延长的时间段,则取决于您的代码<代码>任务.Run
将这些部分卸载到
线程池
线程中,因此调用线程所做的工作尽可能少。我终于站起来与我们的一位高级开发人员交谈,他最终帮助我掌握了一点。在我的头脑中,我似乎经常把异步和并行混为一谈。他还提到,我可能应该避免将操作放在单独的线程中,除非它们相当CPU密集。
async Task<bool> SetupUserAccessControlAsync(int objectId)
{
    var tasks = new List<Task<bool>>();
    tasks.Add(AddToUserRoleBridgeAsync("Everyone", objectId));
    tasks.Add(AddToUserRoleBridgeAsync("Default", objectId));

    return (await Task.WhenAll(tasks)).All(_ => _);
}