2012-09-26 33 views
1

我正在使用通用函數來執行wcf服務調用 - 請參閱下文。 我只是想確保我做正確的事:使用threading.Task來運行WCF方法

  • 最重要的要求就是服務調用應該在單獨的線程執行。最初我想到Backgroundworker然後決定使用Threading.Task所以它很簡單,如
    Task.Factory.StartNew(Function() functionToCall.Invoke(serv))
    並得到結果result = t.Result

  • 請告訴我之探源如果我這樣做:

    昏暗T1作爲新建任務(的對象)(功能()functionToCall.Invoke(SERV))
    t1.Start ()
    結果= t1.Result

  • 我應該考慮Parallel

  • 我錯過了什麼重要的東西嗎?

編輯:此功能是在客戶端解決方案的ServiceProxy項目

Private Function ServiceCall(ByVal functionToCall As ServiceDelegate(Of IEmpService)) As Object 
    Dim channel As New ChannelFactory(Of IEmpService)(_endPoint) 
    Dim serv As IEmpService 
    Dim result As Object = Nothing 

    serv = channel.CreateChannel() 

    Try 
     Dim t As Task(Of Object) = Task.Factory.StartNew(Function() functionToCall.Invoke(serv)) 
     result = t.Result 

    Catch exp As Exception 
     CustomLog.Detail(exp) 

    Finally 
     If channel.State = CommunicationState.Faulted Then 
      channel.Abort() 
     Else 
      channel.Close() 
     End If 
    End Try 

    Return result 
End Function 
+2

您的代碼在'result = t.Result'處被阻止。所以我沒有理由使用Task而不是直接調用方法。 –

+1

L.B是對的。當訪問Task的'Result'屬性時,當前線程等待'Task'完成。所以你開始「Task」並等待它完成一行。這不是如何使用'Task'類的。你只是將工作轉移到另一個線程,但阻止了第一個線程,所以你不會贏得任何東西。 – fero

+0

謝謝。根據你和調用線程(UI)將被阻止,這是我想要的相反。那麼如何正確使用'Task'來做到這一點? – melspring

回答

0

你想要做的方法稱爲同步內的異步調用,它沒有任何意義。

建議您讓此方法同步(刪除與任務相關的代碼),並使用Task/Backgroundworker調用ServiceCall方法。

使用帶有公共方法的新對象將異步調用封裝到同步ServiceCall方法中,並使用事件在接收到數據時返回數據。

讓它使用,如:

var caller = new Caller(); 
caller.Done += { // Your data handling here }; 
caller.Call(Method1); 

在這裏,你可以玩一點點與此對象,通過返回的方法邏輯在構造函數或甚至拉姆達作爲另一個參數調用方法。

一個簡單的方法來實現Event-Based Asynchronous Pattern(EAP)

2

一般來說,如果您希望在沒有其他可以利用的機制的情況下進行調用時,您所概述的模式通常是可以接受的。

但是,在WCF的情況下,您可以生成符合Asynchronous Design Pattern的合同。當您生成您服務引用,點擊「高級」按鈕,然後選擇「生成異步操作」:

Service Reference advanced options dialog

當你這樣做,你的服務合同,將產生返回IAsyncResult interface實現(Begin/End)而不是你的同步操作。

這些比同步操作更受歡迎,因爲它允許你釋放在等待IO完成時(這是一個硬件信號,而不是要求你保持線程的東西)時被阻塞的線程。

從那裏,你可以再調用FromAsync methodTaskFactory class返回一個Task<TResult>(不會阻塞線程要麼),可以用來等待/繼續呼叫異步。

+0

基於事件的異步模式(EAP)>異步編程模型(APM)。 – JoanComasFdz

+0

@JoanComasFdz基於任務的模式>所有這些。問題是,檢查該框只會給你APM版本,而不是EAP版本;您可以從任一個創建基於任務的模式。 – casperOne

+0

如果你可以使用.net 4.5 yes。否則EAP更好更簡單。 – JoanComasFdz