2012-06-15 34 views
0

我正在使用第三方套接字庫,雖然這有點與我的問題無關。該庫由一個「Socket」類組成,其中包含諸如「ConnectAsync」和「WriteAsync」之類的方法。控制在調用其中一個方法後立即返回,並且套接字類引發事件以在操作完成時通知,例如, 「ConnectCompleted」和「WriteCompleted」。當收到數據時,該類還會引發一個事件:「PacketArrived」。C#如何包裝事件驅動的代碼與回調

在我的應用程序中,我想發送數據並等待回覆。因爲這可能發生在許多地方,所以將上面的套接字類包裝在某種幫助程序中是很有意義的,這些幫助程序完成了所有這些工作。我也想它是異步的,所以用戶界面(WPF)未連接/寫過程中凍結/等待回覆,所以輔助方法調用可能是這個樣子: -

SocketHelper.SendData(dataToSend, myCallback); 

在哪裏「當收到數據時調用myCallback。

作爲線程新手,我不確定如何編寫此幫助程序 - 它需要將各種方法和事件串聯在一起,即打開連接,等待連接完成,寫入數據,等待爲了寫入完成,然後等待數據包到達(然後調用提供的回調)。任何幫助讚賞。

+0

開始通過讀取C#事件和委託HTTP底漆://www.akadia。com/services/dotnet_delegates_and_events.html我認爲包裝庫可能是一個過度的橋樑,你不需要通過.NET事件機制傳遞迴調。 –

+1

哪個框架版本? .NET 4有任務並行庫來幫助解決這些問題 –

+0

@PanagiotisKanavos它是.Net 4 –

回答

2

Stephen Toub在「Awaiting Socket Operations」中討論了.NET 4.5的這個主題。通過一些工作,您可以使用與.NET 4相同的技術。

除了使用回調之外,還可以使用任務並行庫至simplify asynchronous calls。使用TPL,您可以將所有套接字操作和回調轉換爲調用操作並處理結果的任務。

任務可以使用像ContinueWith這樣的方法很容易地組成,只有在第一個任務完成時才能執行鏈中的下一個任務。

任務使用線程池中的線程執行,因此您不必關心線程。

TPL已經提供了一種從成對的BeginXXX/EndXXX函數或IAsyncResult對象創建任務的方法。如果你的套接字庫提供這些,你可以馬上開始使用任務。

要使用這些事件,你可以使用TaskCompletionSource從任務並行庫創建,當你調用socket方法和完整的,只有當相應的事件引發,將啓動一項任務。該技術在「Tasks and the Event-based Asynchronous Pattern」中描述。

ParallelExtensionsExtras庫使用此技術爲WebClient, SmtpClient and Ping提供異步方法版本。

使用從「任務和EAP」的代碼,你可以寫你的Socket類這樣的擴展方法:

public static Task ConnectTask(this Socket socket, object address) 
{ 
    var tcs = CreateSource(address); 
    socket.ConnectCompleted += 
     (sender, e) => TransferCompletion(tcs, e,() => e.Result, null); 
    socket.ConnectAsync(address, tcs); 
    return tcs.Task; 
} 

而且使用這樣的:

var connectTask=mySocket.ConnectTask(myaddress); 
connectTask.ContinueWith(t=> { ... }); 

事情變得更在.NET 4.5中更容易。異步/等待關鍵字允許您取消ContinueWith調用並編寫與其同步版本非常相似的代碼。您可以查看「Awaiting Socket Operations」專門針對套接字的擴展。

+0

TaskCompletionSource聽起來很完美。套接字庫僅公開事件(無Begin/EndXxxx方法)。非常感謝。 –