在可能对“空”任务列表调用await 的情况下。
我如何等待 Task<T>
的列表,然后将新任务添加到等待列表中,直到任务失败或完成。
我确信一定有一个 Awaiter
或 CancellationTokenSource
此问题的解决方案。
public class LinkerThingBob
{
private List<Task> ofmyactions = new List<Task>();
public void LinkTo<T>(BufferBlock<T> messages) where T : class
{
var action = new ActionBlock<IMsg>(_ => this.Tx(messages, _));
// this would not actually work, because the WhenAny
// will not include subsequent actions.
ofmyactions.Add(action.Completion);
// link the new action block.
this._inboundMessageBuffer.LinkTo(block);
}
// used to catch exceptions since these blocks typically don't end.
public async Task CompletionAsync()
{
// how do i make the awaiting thread add a new action
// to the list of waiting tasks without interrupting it
// or graciously interrupting it to let it know there's one more
// more importantly, this CompletionAsync might actually be called
// before the first action is added to the list, so I actually need
// WhenAny(INFINITE + ofmyactions)
await Task.WhenAny(ofmyactions);
}
}
我的问题是我需要一种机制,可以添加每个 action
上面创建的实例为Task<T>
当出现异常时将会完成。
我不知道如何最好地解释这一点,但是:
必须至少调用一次
LinkTo<T>
才能完成任务已经完成了,所以我需要从一个无限的任务开始每次
LinkTo<T>
被调用时,必须将新操作添加到任务列表中,该任务可能已在另一个线程中等待。
最佳答案
没有任何内置的东西,但使用 TaskCompletionSource<T>
构建一个并不太难。 。 TCS 是当您想要等待某些内容并且尚未为其构造时使用的类型。 (自定义等待者适用于更高级的场景)。
在这种情况下,类似这样的内容就足够了:
public class LinkerThingBob
{
private readonly TaskCompletionSource<object> _tcs = new TaskCompletionSource<object>();
private async Task ObserveAsync(Task task)
{
try
{
await task;
_tcs.TrySetResult(null);
}
catch (Exception ex)
{
_tcs.TrySetException(ex);
}
}
public void LinkTo<T>(BufferBlock<T> messages) where T : class
{
var action = new ActionBlock<IMsg>(_ => this.Tx(messages, _));
var _ = ObserveAsync(action.Completion);
this._inboundMessageBuffer.LinkTo(block);
}
public Task Completion { get { return _tcs.Task; } }
}
Completion
以未完成状态开始。可以使用ObserveAsync
将任意数量的 block 链接到它。 。一旦其中一个 block 完成,Completion
也完成。我写了ObserveAsync
这里的方式是,如果第一个完成的 block 没有错误地完成,那么 Completion
也会如此。 ;如果第一个完成的 block 完成时出现异常,则 Completion
将完成相同的异常。请随意调整以满足您的特定需求。 :)
关于c# - 创建 ActionBlock<T> 列表,该列表将在任何失败时完成,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34397095/