[英]WCF oneway exception faults channel
我還沒有找到明確的答案。 因此,如果已經對此有疑問,我不好。
我有一個WCF服務,該服務通過回調方法將數據推送到連接的客戶端。 此回調方法是單向的。 因此,每當有新數據時,我都會遍歷連接的用戶並推送數據。 我現在遇到的問題是,當客戶端斷開連接時,它將引發錯誤並且通道出現故障。 我一直以為,不管消息到達目的地,單向都不在乎。 因此,如果沒有客戶,那就運氣不好。 但也不例外。 但是有一個異常,該異常使通道發生故障。
現在,我在某處讀到,如果您啟用可靠的會話,則該異常不會使通道出錯。 這是真的? 單向呼叫發生異常時,如何防止通道進入故障狀態?
您可以存儲在某些資源(例如列表)中的已注冊和可用客戶端的列表。
創建另一個公開Connect / Disconnect方法的接口。 當應用程序啟動並將方法客戶端添加到列表中時,將調用Connect。 應用程序關閉時依次調用斷開連接以擺脫客戶端列表。 OnStartup / OnClosing事件或其等效事件,取決於應用程序客戶端的類型,是指啟動和關閉應用程序的時刻。 這樣的解決方案確保資源僅存儲可訪問的用戶。
[ServiceContract]
interface IConnection
{
[OperationContract(IsOneWay = true)]
void Connect();
[OperationContract(IsOneWay = true)]
void Disconnect();
}
[ServiceContract]
interface IServiceCallback
{
[OperationContract(IsOneWay = true)]
void CallbackMethod();
}
[ServiceContract(CallbackContract = typeof(IServiceCallback))]
interface IService
{
[OperationContract]
void DoSth();
}
class YourService : IConnection, IService
{
private static readonly List<IServiceCallback> Clients = new List<IServiceCallback>();
public void Connect()
{
var newClient = OperationContext.Current.GetCallbackChannel<IServiceCallback>();
if (Clients.All(client => client != newClient))
Clients.Add(newClient);
}
public void Disconnect()
{
var client = OperationContext.Current.GetCallbackChannel<IServiceCallback>();
if (Clients.Any(cl => cl == client))
Clients.Remove(client);
}
public void DoSth()
{
foreach(var client in Clients)
client.CallbackMethod();
}
}
最后,使用IConnection公開另一個端點,以便客戶端可以創建僅用於連接/斷開連接的代理。
編輯:
我知道自從發布answear以來已經有一段時間了,但是我沒有找到准備示例的方法。 解決方法是讓服務的接口派生IConnection,然后僅將服務公開為端點。 我將WCF和WPF應用的簡單示例作為客戶端。 客戶端的應用程序違反了MVVM模式,但在這種情況下無關緊要。 在這里下載。
補充馬克西姆斯所說的話。
我已經在一個類中實現了這種模式,在該類中,客戶端可以訂閱以獲取系統內部狀態的更新,因此監視客戶端可以顯示圖,而其他客戶端則可以執行其他操作(例如,如果某些狀態處於活動狀態則啟用/禁用按鈕)。 當它們出現故障時,它將故障通道從列表中刪除。 當客戶端連接時,還將發送所有當前狀態。
這是代碼,希望對您有所幫助!
[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple)]
public class Publish : IPublish
{
private struct SystemState
{
public string State;
public string ExtraInfo;
}
private static Dictionary<Key<string>, IPublishCallback> mCallbacks = new Dictionary<Key<string>, IPublishCallback>();
private static Dictionary<string, SystemState> mStates = new Dictionary<string, SystemState>();
public void RegisterClient(string name, string system)
{
lock (mCallbacks)
{
IPublishCallback callback = OperationContext.Current.GetCallbackChannel<IPublishCallback>();
Key<string> key = new Key<string>(name, system);
if (!mCallbacks.ContainsKey(key))
{
mCallbacks.Add(key, callback);
}
else
{
mCallbacks[key] = callback;
}
foreach (KeyValuePair<string, SystemState> s in mStates)
{
mCallbacks[key].ServiceCallback(s.Key, s.Value.State, s.Value.ExtraInfo);
}
}
}
public void UnregisterClient(string name)
{
lock (mCallbacks)
{
outer: foreach (var key in mCallbacks.Keys)
{
if (key.Key1 == name)
{
mCallbacks.Remove(key);
goto outer;
}
}
}
}
public void SetState(string system, string state, string extraInfo)
{
lock (mCallbacks)
{
List<Key<string>> toRemove = new List<Key<string>>();
SystemState s = new SystemState() { State = state, ExtraInfo = extraInfo };
SystemState systemState;
if (!mStates.TryGetValue(system, out systemState))
mStates.Add(system, s);
else
mStates[system] = s;
foreach (KeyValuePair<Key<string>, IPublishCallback> callback in mCallbacks)
{
try
{
callback.Value.ServiceCallback(system, state, extraInfo);
}
catch (CommunicationException ex)
{
toRemove.Add(new Key<string>(callback.Key.Key1, callback.Key.Key2));
}
catch
{
toRemove.Add(new Key<string>(callback.Key.Key1, callback.Key.Key2));
}
}
foreach (Key<string> key in toRemove)
mCallbacks.Remove(key);
}
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.