簡體   English   中英

WCF單向異常故障通道

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM