- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一个类的两个实例,它们创建一个 UDP 套接字以从 UDP 客户端接收数据。如果其中一个实例抛出异常,我想立即在更高层处理它。在我的程序中,它们以 await Task.WhenAll(recv1.StartAsync(), recv2.StartAsync)
开始。然而,这会在抛出第一个异常之前等待所有任务完成。关于如何解决此问题的任何想法?
static async Task Main(string[] args)
{
var udpReceiver1 = new UdpReceiver(localEndpoint1);
var udpReceiver2 = new UdpReceiver(localEndpoint2);
var cts = new CancellationTokenSource();
try
{
await Task.WhenAll(udpReceiver1.StartAsync(cts.Token), udpReceiver2.StartAsync(cts.Token));
}
catch (Exception e)
{
// Handle Exception...
cts.Cancel();
}
}
class UdpReceiver
{
public UdpReceiver(IPEndPoint endpoint)
{
udpClient = new UdpClient(endpoint);
}
public async Task StartAsync(CancellationToken cancellationToken)
{
try
{
while (!cancellationToken.IsCancellationRequested)
{
var result = await ReceiveAsync(cancellationToken);
var message = Encoding.UTF8.GetString(result.Buffer);
Trace.WriteLine($"UdpClient1 received message:{Encoding.UTF8.GetString(result.Buffer)}");
// throw new Exception("UdpClient1 raising exception");
}
}
}
private async Task<UdpReceiveResult> ReceiveAsync(CancellationToken cancellationToken)
{
var tcs = new TaskCompletionSource<UdpReceiveResult>();
using (cancellationToken.Register(() => tcs.TrySetCanceled(), false))
{
var task = udpClient.ReceiveAsync();
var completedTask = await Task.WhenAny(task, tcs.Task);
var result = await completedTask.ConfigureAwait(false);
return result;
}
}
private UdpClient udpClient;
}
更新 1:Task.WhenAny 将是一个可行的解决方案。谢谢@CamiloTerevinto
try
{
await await Task.WhenAny(udpReceiver1.StartAsync(cts.Token), udpReceiver2.StartAsync(cts.Token));
}
catch (Exception e)
{
// Handle Exception...
cts.Cancel();
}
更新 2:为了对所有任务进行更细粒度的异常处理,我会使用我自己改编的 Task.WhenAll 实现,由 @Servy 提出。
最佳答案
该行为与框架 WhenAll 实现有很大不同,您可能最好只编写自己的改编版本,幸运的是,实现起来并不是特别困难。只需为每个任务附加一个延续,如果任何任务被取消或出错,生成的任务也会执行相同的操作,如果成功则存储结果,如果最后一个任务是成功的,则使用所有存储的结果完成任务.
public static Task<IEnumerable<TResult>> WhenAll<TResult>(IEnumerable<Task<TResult>> tasks)
{
var listOfTasks = tasks.ToList();
if (listOfTasks.Count == 0)
{
return Task.FromResult(Enumerable.Empty<TResult>());
}
var tcs = new TaskCompletionSource<IEnumerable<TResult>>();
var results = new TResult[listOfTasks.Count];
int completedTasks = 0;
for (int i = 0; i < listOfTasks.Count; i++)
{
int taskIndex = i;
Task<TResult> task = listOfTasks[i];
task.ContinueWith(_ =>
{
if (task.IsCanceled)
tcs.TrySetCanceled();
else if (task.IsFaulted)
tcs.TrySetException(task.Exception.InnerExceptions);
else
{
results[taskIndex] = task.Result;
if (Interlocked.Increment(ref completedTasks) == listOfTasks.Count)
{
tcs.TrySetResult(results);
}
}
});
}
return tcs.Task;
}
与许多基于任务的通用操作一样,您还需要一个没有结果的版本,如果您不想处理显着的开销,您真的需要复制粘贴基于结果的方法,但是所有的结果都被撕掉了,这并不难,只是不够优雅。将所有这些任务转换为有结果的任务也可行,但对于像这样的操作,开销可能有问题。
public static Task WhenAll(IEnumerable<Task> tasks)
{
var listOfTasks = tasks.ToList();
if (listOfTasks.Count == 0)
{
return Task.CompletedTask;
}
var tcs = new TaskCompletionSource<bool>();
int completedTasks = 0;
for (int i = 0; i < listOfTasks.Count; i++)
{
int taskIndex = i;
Task task = listOfTasks[i];
task.ContinueWith(_ =>
{
if (task.IsCanceled)
tcs.TrySetCanceled();
else if (task.IsFaulted)
tcs.TrySetException(task.Exception.InnerExceptions);
else
{
if (Interlocked.Increment(ref completedTasks) == listOfTasks.Count)
{
tcs.TrySetResult(true);
}
}
});
}
return tcs.Task;
}
关于c# - 立即捕获异常不适用于 Task.WhenAll,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64053239/
我正在审查一些代码并试图找出您应该或不应该使用 Task.WhenAll(Tasks[]) 的技术原因。本质上是并行进行 Http 调用。 Http 调用调用不同的微服务,我猜其中一个调用可能需要一些
有时我想并行等待一堆任务,但任务本身取决于某些条件。我会写 var tasks = new List { DoThisAsync(), DoThatAsync() }; if (condition)
我有一个方法可以生成一系列任务( See my previous post about threading ),在这个方法结束时,我有以下选项: await Task.WhenAll(tasks);
当前使用以下代码等待任务集合完成。但是,我现在遇到这样一种情况,我希望能够通过取消 token 取消/中止WhenAll调用。我该怎么办? Dim TaskCollection As New Li
每次运行以下程序都会捕获 Mike 的异常。 WhenAll 是顺序涉及每个任务之间的连续上下文还是所有任务都同时运行?如果它是并发的,为什么总是捕获 Mike 的异常而不是 Mitch 的异常。我推
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 这个问题似乎与 help center 中定义的范围内的编程无关。 . 关闭 7 年前。 Improve
我需要让 UI 线程等待任务数组完成执行。下面代码的问题是 - 任务反过来调用 UI 线程写入文本框。如何解决这个问题? public partial class FormConsole : Form
考虑以下理想代码(它不起作用)。我实际上是在尝试创建 Task 的列表返回特定对象的 s,将它们与 string 相关联标识符,然后使用 Task.WhenAll 批量执行所有这些.在执行结束时,我需
我有一个类的两个实例,它们创建一个 UDP 套接字以从 UDP 客户端接收数据。如果其中一个实例抛出异常,我想立即在更高层处理它。在我的程序中,它们以 await Task.WhenAll(recv1
这个问题在这里已经有了答案: An async/await example that causes a deadlock (5 个回答) 4年前关闭。 我是 C# 任务的新手,遇到了一个我不理解的问题
我有两个异步方法作为单独的线程/任务在窗体窗口的后台运行。这些是无限循环,只是在后台做一些工作,然后使用调度程序更新 UI。见下文。 public async Task RunCameraTh
我有一个简单的 Winforms 应用程序。我想后台 TCP 连接/打印请求,并在我的代码中的设定点检查所有任务的输出。 我希望 ReportOnTasks阻止直到 WaitAll完成了。请有人能解释
我对异步编程还很陌生。我想在等待其中任何一个任务之前启动一系列任务(发出 http 请求)。 List identifiers; //Set identifiers to what they shou
我有一些关于 TPL 的问题。正如您所看到的,我正在创建 2 个简单的任务并将它们添加到列表中。问题(预期行为)是任务在 WorkMethodAsync 中点击“await”后立即返回,因此使 Tas
我正在尝试理解 async/await 并想知道这是否是 Task.WhenAll 的正确使用方式方法: public class AsyncLib { public async Task>
我有一堆任务定义为: Task t1 = new Task( () => { /* Do Something */ } ); Task t2 = new Task( () => { /* Do Som
我经常有一些代码,其中我有一组独立任务,这些任务创建了可以立即启动的其他独立任务的集合,所以就时间而言,它看起来像下面这样。 A0 ------- B0 --------- C0
跟随 this question (及其答案)我想使用 TaskCompletionSource 和 Task.WhenAll 等待任何任务首先返回 True 。所以我写了这个: TaskComple
我有以下两种方法,它们产生相同的结果。 public static async Task> ExecuteSqlStoredProcedureSelect(IEnumerable linkedAcco
有没有非阻塞的Task.WaitAll类似于 Task.WhenAll ,但不是平行的? 这是我写的,但也许它是内置的? public async Task> AwaitAllAsync(IEnume
我是一名优秀的程序员,十分优秀!