我正在嘗試使用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