防止 WCF 雙工回調服務出現死鎖問題
我有一個自託管 wcf 雙工回調服務的問題。我收到一條
InvalidOperationException消息:此操作將死鎖,因為在目前消息完成處理之前無法接收到回复。如果要允許無序消息處理,請在 CallbackBehaviorAttribute 上指定 Reentrant 或 Multiple 的 ConcurrencyMode。
這是我的服務行為:
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Reentrant, UseSynchronizationContext = true)]這是我的服務契約:
[ServiceContract(SessionMode = SessionMode.Required, CallbackContract = typeof(IClientCallback))] [ServiceContract] public interface IClientToService { [OperationContract(IsOneWay = false)] LVSSStatus GetLvssStatus(); [OperationContract(IsOneWay = true)] void PickSpecimen(long trackingNumber, int destCode); [OperationContract(IsOneWay = true)] void CancelCurrentPickTransaction(); }這是我的回調介面:
public interface ILvssClientCallback { [OperationContract(IsOneWay = true)] void SendClientCallback(LvssCallbackMessage callbackMessage); [OperationContract(IsOneWay = false)] List<SpecimenTemplateDescriptor> GetTemplateDescriptorList(DrawerLayout drawerLayout); [OperationContract(IsOneWay = false)] SpecimenTemplate SelectSpecimenTemplate(string templateName, int version); [OperationContract] void SpecimenStoredInContainer(string containerID, bool isValidRackID, int rackRow, int rackCol, int deckRow, int deckCol, int drawerRow, int drawerCol, long trackingNumber, RobotErrors robotError); [OperationContract] void LvssRobotStatusChange(LVSSStatus status); }我知道這
InvalidOperationException是在客戶端上呼叫回調操作時引起的,該服務已經被鎖定以處理目前操作。因此,發生了死鎖。我嘗試將我的 ConcurrencyMode 更改為多個,並將 UseSynchronizationContext 更改為 false。
我的服務仍然存在兩個問題:
首先: 以下服務操作在
GetLvssStatus()快速呼叫時凍結我的客戶端 wpf 應用程序(通過快速點擊 UI 按鈕)。該方法不是一種方式,而是從服務同步返回一個列舉類型給客戶端。[OperationContract(IsOneWay = false)] LVSSStatus GetLvssStatus();*** 在這種情況下,是什麼導致我的 wpf 應用程序凍結?***我可以做些什麼來防止應用程序凍結?如果我使用 backgroundworker 執行緒作為非同步呼叫,應用程序不會凍結。我真的需要這種方法來同步工作。
**第二:**當我將回調方法 LvssRobotStatusChange 分配給 時
IsOneWay = true,我得到一個 ObjectDisposedException:無法訪問已處置的對象。對象名稱:'System.ServiceModel.Channels.ServiceChannel'。[OperationContract(IsOneWay = true)] void LvssRobotStatusChange(LVSSStatus status);*** 是什麼導致了這個 ObjectDisposedException?***在這種情況下可以省略 IsOneWay 賦值嗎?在這種情況下省略 IsOneWay 允許回調完成而沒有任何異常。
*** 這些問題可能是由於缺少執行緒安全程式碼造成的嗎?
***如果是這樣,使 ConcurrencyMode.Multiple 服務行為執行緒安全的最佳實踐是什麼?
非常感謝您對這些問題的任何幫助。
***第一次編輯關於創建我的雙工頻道的更多資訊。我的 wpf 視圖模型創建了一個代理對象,負責處理我的頻道的創建。到目前為止,當服務嘗試使用回調對象時,任何嘗試在客戶端的新執行緒上設置我的通道都會導致 ObjectDisposedException。
***第二次編輯我相信如果我可以使用 void 方法設置 IsOneWay = true 的操作契約,我的服務應該可以工作。在可重入並發的情況下,主通道執行緒應該讓這些方法通過,而不管任何鎖定。
這是我的回調介面:
public interface ILvssClientCallback { [OperationContract(IsOneWay = true)] void SendClientCallback(LvssCallbackMessage callbackMessage); [OperationContract] List<SpecimenTemplateDescriptor> GetTemplateDescriptorList(DrawerLayout drawerLayout); [OperationContract] SpecimenTemplate SelectSpecimenTemplate(string templateName, int version); [OperationContract(IsOneWay = true)] void SpecimenStoredInContainer(string containerID, bool isValidRackID, int rackRow, int rackCol, int deckRow, int deckCol, int drawerRow, int drawerCol, long trackingNumber, RobotErrors robotError); [OperationContract(IsOneWay = true)] void LvssRobotStatusChange(LVSSStatus status); }當我將方法 LvssRobotStatuschange 操作契約設置為 IsOneWay = true 時,我的記憶體回調通道會引發 CommunicationObjectAbortedException。由於某種原因,我的回調屬性被中止。
***什麼會導致回調通道中止?
我之前遇到過這個問題,這個連結應該會有所幫助,它討論了在應用程序主執行緒以外的執行緒上創建通道。
我遇到的問題:
CallBackHandlingMethod() { requestToService(); // deadlock message. }出路:
CallBackHandlingMethod() { Task.Factory.StartNew(()=> { requestToService(); }); }