1

したがって、私は wcf サービス、特に duplex について学び始めてまだ数日で、テスト アプリから始めています。目標は、変数を格納する内部 (静的?) クラスを持つ Service と、それらの変数をフェッチする Client を持つことです。

現在、Storage クラスには 2 つの変数があります。1 つは Subscribers のリスト ( ObservableCollection<IMyContractCallBack>) で、もう 1 つは ですObservableCollection<string>。各文字列はコールバック メソッドでクライアントに送信されます。

Fetchサーバー側のコレクション内の文字列をクライアント (サーバー側のコレクションにコンテキストを追加することによって、まだサブスクライブしていない場合は最初にサブスクライブします) を取得できるようにしたいと考えています。その部分は期待どおりに機能します。Pushただし、サーバーからサブスクリプション リスト内のすべてのクライアントに文字列を送信したり、Add文字列のコレクションに文字列を送信したりしたいと考えています。それが私の問題が発生する場所です。

いつでもFetch、文字列リスト「test1...」と「test2...」に追加して送信すると、クライアントはテキストブロックUI(wpa)を更新するため、2回フェッチすると、"test1...","test2...","test1...","test2..."現在チェックがないため、取得できます重複用。Fetchこれは、コレクションが からまでサーバー側で更新および記憶できることを証明していますFetch。ただし、特定のテキストを入力しようとするとAddSendすべての変数が忘れられてしまうため、購読者リストは null になり、追加先リストは空になります。それでも、Fetchもう一度、古いリストが戻ってきました(現在は6つのものがありますtest1...,test2... etc...

授業前にこれを持っています

[ServiceBehavior(InstanceContextMode= InstanceContextMode.PerSession, ConcurrencyMode = ConcurrencyMode.Single)]

また、シングルトン コンテキスト モードを試してみましたが、役に立ちませんでした。を Multiple に変更しConcurrencyModeても、何も変わりません。内部コマンドがサーバー自体から送信された場合にのみ静的データがリセットされる理由についてのアイデアはありますか?

私のサービスのコードは次のとおりです。

namespace WcfService3
{   
[ServiceBehavior(InstanceContextMode= InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Single)]
public class Service1 : IService1
{
    public static event Action NullContext;

    public static ObservableCollection<IMyContractCallBack> Subscriptions;

    public void     NormalFunction()
    {

        //Only sends to Subs that are STILL Open
        foreach (IMyContractCallBack user in Subscriptions)
        {
            //Removes the Closed users, because they are hanging around from last session
            if (((ICommunicationObject)user).State != CommunicationState.Opened)
            {
                Subscriptions.Remove(user);
            }
            else
            {
                ObservableCollection<string> holder = Storage.GetList();

                foreach (string str in holder)
                {
                    user.CallBackFunction(str);
                }
            }
        }
    }
    public static void Send(string str)
    {
        try
        {
            foreach (IMyContractCallBack user in Subscriptions)
            {
                user.CallBackFunction(str);
            }
        }
        catch
        {
            //For some reason 'Subscriptions' is always null
            NullContext.Invoke();
        }
    }
    public static void Add(string str)
    {
        //For some reason 'SendList' is always null here, too
        Storage.AddToList(str);
        if (Subscriptions != null)
        {
            //For same reason 'Subscriptions' is always null
            foreach (IMyContractCallBack user in Subscriptions)
            {
                user.CallBackFunction(str);
            }
        }
    }

    public void Subscribe()
    {
        //Adds the callback client to a list of Subscribers
        IMyContractCallBack callback = OperationContext.Current.GetCallbackChannel<IMyContractCallBack>();
        if (Subscriptions == null)
        {
            Subscriptions = new ObservableCollection<IMyContractCallBack>();
        }
        if(!Subscriptions.Contains(callback))
        {
            Subscriptions.Add(callback);
        }
    }

Storageクラスのコードは次のとおりです。

namespace WcfService3
{
public static class Storage
{

    public static readonly ObservableCollection<string> SendList = new ObservableCollection<string>();

    public static IMyContractCallBack callback;

    public static ObservableCollection<string> GetList()
    {

        if (SendList.Count == 0)
        {
            AddToList("Test1...");
            AddToList("Test2...");
        }

        return SendList;
    }

    public static void AddToList(string str)
    {


            SendList.Add(str);

    }
}

}

必要に応じて、さらにコードを提供できます。

4

1 に答える 1

0

ThreadStaticどこでも属性を使用していますか? (簡単な検索を行うだけです)それは本当のロングショットであり、おそらくあなたの問題ではありません.

おそらくスレッドの問題があります。すべてのクライアントが同時に接続していますか (つまり、連続して接続しているということですか?) 接続している場合、Subscribeメソッド内の次のコードでスレッド化の問題が発生します。

   if (Subscriptions == null)
    {
        Subscriptions = new ObservableCollection<IMyContractCallBack>();
    }

メソッドへのアクセスをより適切に制限して、Subscriptions誰がいつ変更したかを確認し、コンソール ステートメントを使用してどこが間違っているかを把握できるようにする必要があります。

于 2012-07-23T14:16:43.980 に答える