2013-04-02 104 views
2

我們有一個以下列方式處理傳入消息的WCF服務:在任務中進行異步/等待數據庫調用?

public bool ProcessMessage(string message) 
{ 
    var returnValue = GetReturnValue(); 

    Task.Run(() => { 
     //do some things with the message 
     UpdateDatabase(); 
     SendRepliesOverNetwork(); 
    }); 

    return returnValue; 
} 

在努力處理儘可能多的信息越好,我們在這裏添加任務。我們希望儘快將returnValue返回給調用者,並讓Task完成它的工作。

我的問題:使用等待異步數據庫調用和/或使用異步方法進行網絡回覆有什麼優勢嗎?

我很謹慎,因爲我認爲這可能會造成太多的上下文切換。我們已經看到該應用使用了100多個加載線程。

+0

這真的取決於你的應用程序的情況下,你要立即進行發送數據庫更新後UI響應,還是你想要做的性能考慮? –

+0

我不認爲你在等待任何東西:你在ThreadPool上排隊工作並立即返回給調用者。 –

+0

@KyleC:表現。試圖儘可能快地處理儘可能多的消息。 – jeremywho

回答

7

首先,我建議你退後一步,確實詢問早點回來是否是一個好主意。你在做什麼通常是危險的;在進行實際處理之前,您將「確定」返回給客戶端。如果您的客戶知道「returnValue」並不意味着該操作已完成,並且只在收到「SendReplies」時才認爲它已完成,那麼這只是一個好主意。

也就是說,你應該看到一些可以使你的所有事情異步的好處。如果你所有的任務都是非阻塞的,你可以更好地使用線程池(更少的上下文切換)。

public bool ProcessMessage(string message) 
{ 
    var returnValue = GetReturnValue(); 

    Task.Run(async() => { 
    //do some things with the message 
    await UpdateDatabaseAsync(); 
    await SendRepliesOverNetworkAsync(); 
    }); 

    return returnValue; 
} 
+0

returnValue基本上是一個應用程序級別,用於告訴調用者我們收到了它的消息。因此,在通話壽命之外進行處理是很好的。我會繼續嘗試異步數據庫/網絡調用。 – jeremywho

4

我可以看到這種方法的一些潛在問題。

首先,如果您在IIS中託管WCF服務,則使用比請求長的後臺線程是一個很大的禁忌。當請求完成時,IIS可以自由拆除整個AppDomain,這將以極端偏見中止所有後臺工作!其次,如果現有工作正在進行,WCF將限制請求。使用這種模式,您可以快速處理請求,並且可以毫無限制地增加爲線程池排隊的工作量。


您可以嘗試使用WCF異步服務方法。這將釋放只等待IO的線程 - 數據庫和網絡訪問 - 這可以提高吞吐量。

有一個深入的文章對這種做法在這裏:Dan Rigsby: Async Operations in WCF

此外,還有在MSDN這裏部分:WCF: Synchronous and Asynchronous Operations

+0

wcf服務是自我託管的,所以我認爲它應該沒問題。我會研究一下wcf的異步方法。 – jeremywho

+0

由於該服務是自託管的,因此它現在變成了*你的*問題而不是IIS'。考慮應用關鍵服務器操作系統安全更新的計劃;你需要一種方法來告訴wcf服務不忙。 –