1

クライアントがサーバーに接続する単純な二重サービスをセットアップしようとしています。接続されたクライアントは、BookAddedサービス操作を実行できます。これが発生すると、サーバーは、接続されているすべてのクライアントでコールバックを発生させて、変更を通知することになっています。

コールバック操作が を使用して UI スレッドで何かを実行する必要があることを除いて、コールバックは正常に機能しているようDispatcher.BeginInvokeです。

私の場合、Console.WriteLine("Callback thread")購入は実行されConsole.WriteLine("Dispatcher thread")ません。これの理由は何ですか?

私のサービス契約:

public interface ICallback
{
    [OperationContract(IsOneWay = true)]
    void BookAdded(string bookId);
}

[ServiceContract(
    CallbackContract = typeof(ICallback), 
    SessionMode = SessionMode.Required)]
public interface IService
{
    [OperationContract]
    bool BookAdded(string bookId);
}

私のサービスの実装:

[ServiceBehavior(
    UseSynchronizationContext = false,
    InstanceContextMode = InstanceContextMode.PerSession, 
    ConcurrencyMode = ConcurrencyMode.Reentrant)]
public class MyService : IService
{
    public bool BookAdded(string bookId)
    {
        try
        {
            Console.WriteLine("Client Added Book " + bookId);

            foreach (ICallback callback in connectedClients)
            {
                callback.BookAdded(bookId);
            }
        }
        catch (Exception e)
        {
            Console.WriteLine(e.Message);
        }
        return true;
    }
}

私のクライアントの実装:

[CallbackBehavior(UseSynchronizationContext = false, ConcurrencyMode = ConcurrencyMode.Multiple)]
public class MyCallBack: ICallback, IDisposable
{
    private Dispatcher theDispatcher;
    private InstanceContext context;
    private WcfDuplexProxy<IService> proxy;

    [ImportingConstructor]
    public MyCallBack()
    {  
        theDispatcher = Dispatcher.CurrentDispatcher;
        context = new InstanceContext(this);
        proxy = new WcfDuplexProxy<IService>(context);

        proxy.Connect();
    }

    public IService Service
    {
        get
        {
            return proxy.ServiceChannel;
        }
    }

    public void CallServiceOperation()
    {
        Service.BookAdded("BOOK1234");
    }

    public void BookAdded(string bookId)
    {
        Console.WriteLine("Callback thread");
        theDispatcher.BeginInvoke(new Action(() => { Console.WriteLine("Dispatcher thread"); }));
    }

    public void Dispose()
    {
        Service.Disconnect();
        proxy.Close();
    }
4

2 に答える 2

3

私が考えているのは、UI スレッドがまだ終了していないサーバー ウィッチへの元の呼び出しでまだブロックされているということです。 クライアントの同時実行モードを再入可能に変更すると、うまくいくと思います。. 必要なことは、コールバックで [CallbackBehavior(UseSynchronizationContext = false)] を設定することです。

この記事では、この問題について非常によく説明しています。

GJ

于 2011-04-03T12:59:14.563 に答える
0

私はあなたと同様の問題に遭遇したと思います。Dispatcher.beginInvoke を呼び出す新しいスレッドで解決しました。私が理解しているように、UI スレッドはサービスにリクエストを送信します。サービスは、サービス操作中にクライアントに実装するコールバック コントラクトを呼び出します。したがって、コールバック操作で、サービス操作からの応答を待機するために保留中の UI スレッドのコントロールを呼び出す場合。これが、クライアントがデッドロック状態になる理由です。したがって、以下のコードを試すことができます。 Thread th=new Thread(new ThreadStart(()=>{Console.WriteLine("Callback thread");
theDispatcher.BeginInvoke(new Action(() => { Console.WriteLine("Dispatcher thread"); }));
})); th.Start();

于 2012-07-20T06:42:34.090 に答える