我有一个带ActionBlock的类Receiver:
public class Receiver<T> : IReceiver<T>
{
private ActionBlock<T> _receiver;
public Task<bool> Send(T item)
{
if(_receiver!=null)
return _receiver.SendAsync(item);
//Do some other stuff her
}
public void Register (Func<T, Task> receiver)
{
_receiver = new ActionBlock<T> (receiver);
}
//...
}
ActionBlock的Register-Action是一个带有await-Statement的异步方法:
private static async Task Writer(int num)
{
Console.WriteLine("start " + num);
await Task.Delay(500);
Console.WriteLine("end " + num);
}
现在,我要做的是同步等待(如果设置了条件),直到操作方法完成以获取独占行为:
var receiver = new Receiver<int>();
receiver.Register((Func<int, Task) Writer);
receiver.Send(5).Wait(); //does not wait the action-await here!
问题是当“await Task.Delay(500);”时语句被执行,“receiver.Post(5).Wait();”不再等待。
我尝试了几种变体(TaskCompletionSource,ContinueWith等),但是它不起作用。
有谁知道如何解决这个问题?
最佳答案
默认情况下,ActionBlock
将强制执行独占行为(一次仅处理一项)。如果您通过“专有行为”表示其他含义,则可以在操作完成时使用TaskCompletionSource
通知发件人:
... use ActionBlock<Tuple<int, TaskCompletionSource<object>>> and Receiver<Tuple<int, TaskCompletionSource<object>>>
var receiver = new Receiver<Tuple<int, TaskCompletionSource<object>>>();
receiver.Register((Func<Tuple<int, TaskCompletionSource<object>>, Task) Writer);
var tcs = new TaskCompletionSource<object>();
receiver.Send(Tuple.Create(5, tcs));
tcs.Task.Wait(); // if you must
private static async Task Writer(int num, TaskCompletionSource<object> tcs)
{
Console.WriteLine("start " + num);
await Task.Delay(500);
Console.WriteLine("end " + num);
tcs.SetResult(null);
}
另外,您可以使用
AsyncLock
(included in my AsyncEx library):private static AsyncLock mutex = new AsyncLock();
private static async Task Writer(int num)
{
using (await mutex.LockAsync())
{
Console.WriteLine("start " + num);
await Task.Delay(500);
Console.WriteLine("end " + num);
}
}
关于c# - 在ActionBlock中等待异步lambda,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/13704087/