2010-04-09 84 views
0

我有一個提供登錄方法的WCF服務。客戶需要調用此方法(因爲它是唯一的IsInitiating = true)。這種方法應該返回一個描述調用成功的字符串。如果登錄失敗,連接應該關閉。WCF:如何正常關閉連接時發送數據?

問題是關閉的時間。我想發送返回值,然後立即關閉連接。

string Login (string name, string pass) 
{ 
    if (name != pass) { 
     OperationContext.Current.Channel.Close(); 
     return "fail"; 
    } 
    else { 
     return "yay"; 
    } 
} 

MSDN狀態,該信道

上調用Close導致ICommunicationObject到 從打開狀態 優雅地轉換到關閉狀態。關閉 方法允許任何未完成的工作返回前完成 。例如,對於 示例,完成發送任何緩衝的 消息)。

這對我沒有幫助(或者我的理解是錯誤的),因爲close立即執行 - WCF不會等待Login方法完成執行並返回一個字符串,但會關閉之前的連接。

因此,我認爲調用Close並不等待正在運行的方法完成。現在,我還能如何返回一個值,,然後關閉?

在我的絕望中,我嘗試了以下方法,但它不是一個嚴肅的解決方案。

new Thread (() => { 
    Thread.Sleep (100); 
    OperationContext.Current.Channel.Close(); 
}).Start(); 

回答

6

當文檔說「優雅」時,它確實在談論您何時從客戶端側調用ICommunicationObject.Close。在服務一側,如果您嘗試在客戶端仍在等待響應時關閉該通道,那麼您的時間將會很糟糕。

客戶端會感到困惑,而不是打擾承認關閉,那麼服務器將嘗試執行其Close嘗試,這種情況發生在工作線程上,而未處理的工作線程上的異常不利於您服務的健康或你自己的理智。

你真正想要的不是一個完美的連接,而是想要強制斷開無法成功登錄的客戶端。爲了做到這一點,你必須註冊時完成操作的事件處理程序,後的響應發送:

public string Login(string name, string pass) 
{ 
    if (name != pass) 
    { 
     OperationContext.Current.OperationCompleted += LoginFailed; 
     return "fail"; 
    } 
    return "yay"; 
} 

private void LoginFailed(object sender, EventArgs e) 
{ 
    OperationContext.Current.Channel.Abort(); 
} 

這將做什麼,我敢肯定,你想要的 - 發送「失敗「回到客戶端,清理所有需要清理的內容,然後斷開客戶端連接,阻止會話進一步活動。順便說一句,我不知道這與真實的服務代碼有多接近,但是當你只能使用WCF的內置服務憑證系統時,在服務上有一個「Login」方法有點多餘。

+0

好的解釋!是的,那正是我想要的。 OperationCompleted事件聽起來像個不錯的主意,我會嘗試。關於證書系統:我認爲這在我的具體情況下是過分的,但我會記住並稍後看看。 – mafu 2010-04-10 12:31:38

0

爲什麼要關閉連接服務器端?我知道你想盡快清理任何資源。但是,爲什麼不通過使用WCF提供的可用限制(實例模式等)和超時選項來進行管理?

相關問題