我正在尝试使用TPL数据流,通过移植一些旧的套接字代码来使用TPL数据流和新的异步功能。尽管API感觉很稳定,但我的代码仍然感觉凌乱。我想知道我是否在这里错过了一些东西。TPL数据流使用异步操作
我的要求如下:一个套接字类公开:打开,关闭,发送和接收方法。所有返回一个任务,因此是异步的。打开和关闭是原子的。发送和接收可以彼此相邻,尽管两者一次只能处理1条命令。
逻辑上,这使我对内部控制的下一段代码:
// exposing an exclusive scheduler for connectivity related tasks and a parallel scheduler where send and receive can work with
private readonly ConcurrentExclusiveSchedulerPair exclusiveConnectionSchedulerPair;
private readonly ActionBlock<Action> connectionBlock;
private readonly ActionBlock<Action> sendBlock;
private readonly ActionBlock<Action> receiveBlock;
// within the constructor:
this.exclusiveConnectionSchedulerPair = new ConcurrentExclusiveSchedulerPair();
this.connectionBlock = new ActionBlock<Action>(action => action(), new ExecutionDataflowBlockOptions() { TaskScheduler = exclusiveConnectionSchedulerPair.ExclusiveScheduler });
this.sendBlock = new ActionBlock<Action>(action => action(), new ExecutionDataflowBlockOptions() { TaskScheduler = exclusiveConnectionSchedulerPair.ConcurrentScheduler });
this.receiveBlock = new ActionBlock<Action>(action => action(), new ExecutionDataflowBlockOptions() { TaskScheduler = exclusiveConnectionSchedulerPair.ConcurrentScheduler });
到目前为止都很好。我可以安全地将操作发送到发送和接收模块,而无需担心与此同时运行的连接相关操作。另外ActionBlock确保多个发送调用是同步的(同上接收,关闭和打开)。
问题是,没有简单的方法将任务传回给海报。现在我正在使用TaskCompletionSource传递结果。喜欢:
public Task Send(ArraySegment<byte> buffer, CancellationToken cancellationToken)
{
TaskCompletionSource<object> resultCompletionSource = new TaskCompletionSource<object>();
sendBlock.Post(async() =>
{
if (!tcpClient.Connected)
throw new InvalidOperationException("Cant send when not open");
else
{
await sendStream.WriteAsync(buffer.Array, buffer.Offset, buffer.Count, cancellationToken);
resultCompletionSource.SetResult(null);
}
});
return resultCompletionSource.Task;
}
这只是感觉丑陋和笨拙。我的问题是:有没有办法使用TPL同步工作流而不必使用TaskCompletionSource进行通信?
谢谢!
我没有使用TPL数据流,所以这可能是遥远,但如果你需要的动作完成时就知道了,好像你不希望发布Post的'fire and forget',而应该使用SendAsync,以便让Task返回而不是? http://msdn.microsoft.com/en-us/library/hh194681(v=vs.110) –
据我了解,当帖子被接受或明确拒绝时,SendAsync会返回一个任务。因为我使用无限制的动作块。帖子将始终被直接接受。 SendAsync不能帮助我的案例 – Polity