Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/asp.net-core/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何在.NET Core中执行多个任务,并检查哪些任务已成功完成_C#_Asp.net Core_Exception_Async Await_Task - Fatal编程技术网

C# 如何在.NET Core中执行多个任务,并检查哪些任务已成功完成

C# 如何在.NET Core中执行多个任务,并检查哪些任务已成功完成,c#,asp.net-core,exception,async-await,task,C#,Asp.net Core,Exception,Async Await,Task,我正在尝试执行以下场景: 创建多个任务 所有任务都在相同的结构中,相同的代码具有不同的参数 结构是:尝试执行,如果失败则捕获,并抛出异常/异常 并行运行它们并等待它们完成 完成后,检查哪些任务引发异常,哪些任务成功,而不引发异常 您是否错过了在ToDictionary中调用ExecuteRequest的等待 async name => await ExecuteRequest 您是否错过了在ToDictionary中调用ExecuteRequest的等待 async name =>

我正在尝试执行以下场景:

创建多个任务 所有任务都在相同的结构中,相同的代码具有不同的参数 结构是:尝试执行,如果失败则捕获,并抛出异常/异常 并行运行它们并等待它们完成 完成后,检查哪些任务引发异常,哪些任务成功,而不引发异常
您是否错过了在ToDictionary中调用ExecuteRequest的等待

async name => await ExecuteRequest

您是否错过了在ToDictionary中调用ExecuteRequest的等待

async name => await ExecuteRequest

您无法避免在等待Task.WhenAll时引发异常。这是故意的行为。 但您可以通过任务的结果值传递任务的状态。只需将结果从字符串扩展到字符串结果,bool Success并从catch返回false Success,而无需重新抛出异常

public class Controller : ControllerBase
{
    private readonly List<string> _names = new List<string>()
    {
        "name1",
        "name2"
    };

    [HttpGet]
    public async Task<ActionResult> Get()
    {
        // Leaving this processing because it is the same in the original code, maybe there is something here that is relevant
        var tasks = _names.ToDictionary(name => name, name => ExecuteRequest(name, async (value) =>
        {
            return await ReturnOrThrow(value);
        }));

        await Task.WhenAll(tasks.Values); // Doesn't throw exception anymore, but you can access Success status from Task's Result tuple

        var namesThatSucceeded = tasks.Count(t => t.Value.Result.Success);
        var namesThatThrewException = tasks.Count(t => !t.Value.Result.Success);

        return Ok(new
        {
            Succeeded = namesThatSucceeded,
            Failed = namesThatThrewException
        });
    }

    // The "generic task structure" that runs the request, catches exception if thrown, and re-throws it.
    private async Task<(string Result, bool Success)> ExecuteRequest(string name, Func<string, Task<string>> request)
    {
        try
        {
            return (await request(name), true);
        }
        catch (HttpRequestException e)
        {
            Console.WriteLine(e.Message);
            return (null, false);
        }
    }

    // The actual processing
    private async Task<string> ReturnOrThrow(string name)
    {
        if (name == "name1")
        {
            throw new HttpRequestException();
        }

        return await Task.FromResult(name);
    }
}

不客气。

您无法避免在等待任务时抛出异常。这是故意的行为。 但您可以通过任务的结果值传递任务的状态。只需将结果从字符串扩展到字符串结果,bool Success并从catch返回false Success,而无需重新抛出异常

public class Controller : ControllerBase
{
    private readonly List<string> _names = new List<string>()
    {
        "name1",
        "name2"
    };

    [HttpGet]
    public async Task<ActionResult> Get()
    {
        // Leaving this processing because it is the same in the original code, maybe there is something here that is relevant
        var tasks = _names.ToDictionary(name => name, name => ExecuteRequest(name, async (value) =>
        {
            return await ReturnOrThrow(value);
        }));

        await Task.WhenAll(tasks.Values); // Doesn't throw exception anymore, but you can access Success status from Task's Result tuple

        var namesThatSucceeded = tasks.Count(t => t.Value.Result.Success);
        var namesThatThrewException = tasks.Count(t => !t.Value.Result.Success);

        return Ok(new
        {
            Succeeded = namesThatSucceeded,
            Failed = namesThatThrewException
        });
    }

    // The "generic task structure" that runs the request, catches exception if thrown, and re-throws it.
    private async Task<(string Result, bool Success)> ExecuteRequest(string name, Func<string, Task<string>> request)
    {
        try
        {
            return (await request(name), true);
        }
        catch (HttpRequestException e)
        {
            Console.WriteLine(e.Message);
            return (null, false);
        }
    }

    // The actual processing
    private async Task<string> ReturnOrThrow(string name)
    {
        if (name == "name1")
        {
            throw new HttpRequestException();
        }

        return await Task.FromResult(name);
    }
}

不客气。

您可以使用具有等待和异常处理程序的高阶函数包装操作

 class Program
{
    static async Task Main(string[] args)
    {
        var itemsToProcess = new[] { "one", "two" };
        var results = itemsToProcess.ToDictionary(x => x, async (item) =>
        {
            try
            {
                var result = await DoAsync();
                return ((Exception)null, result);
            }
            catch (Exception ex)
            {
                return (ex, (object)null);
            }
        });

        await Task.WhenAll(results.Values);

        foreach(var item in results)
        {
            Console.WriteLine(item.Key + (await item.Value).Item1 != null ? " Failed" : "Succeed");
        }
    }

    public static async Task<object> DoAsync()
    {
        await Task.Delay(10);
        throw new InvalidOperationException();
    }
}

您可以使用具有等待和异常处理程序的高阶函数包装操作

 class Program
{
    static async Task Main(string[] args)
    {
        var itemsToProcess = new[] { "one", "two" };
        var results = itemsToProcess.ToDictionary(x => x, async (item) =>
        {
            try
            {
                var result = await DoAsync();
                return ((Exception)null, result);
            }
            catch (Exception ex)
            {
                return (ex, (object)null);
            }
        });

        await Task.WhenAll(results.Values);

        foreach(var item in results)
        {
            Console.WriteLine(item.Key + (await item.Value).Item1 != null ? " Failed" : "Succeed");
        }
    }

    public static async Task<object> DoAsync()
    {
        await Task.Delay(10);
        throw new InvalidOperationException();
    }
}

抑制等待任务异常的简单方法是将任务作为单个参数传递给:

创建一个任务,该任务将在提供的任何任务完成时完成

这是因为任务从task.when返回,而任何任务都不会失败。当它完成时,它总是成功完成。但有两个小缺点:

它没有明确传达其意图,因此建议添加评论。 此方法接受params Task[]参数,因此调用它会导致对象分配,避免在热路径中使用它。
抑制等待任务异常的简单方法是将任务作为单个参数传递给:

创建一个任务,该任务将在提供的任何任务完成时完成

这是因为任务从task.when返回,而任何任务都不会失败。当它完成时,它总是成功完成。但有两个小缺点:

它没有明确传达其意图,因此建议添加评论。 此方法接受params Task[]参数,因此调用它会导致对象分配,避免在热路径中使用它。
你看到的异常是什么?你看到的异常是什么?