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[]参数,因此调用它会导致对象分配,避免在热路径中使用它。
你看到的异常是什么?你看到的异常是什么?