Дуплексный обратный вызов WCF в приложении WPF: Dispatcher.BeginInvoke не выполняет делегат - PullRequest
1 голос
/ 01 апреля 2011

Я пытаюсь настроить простой дуплексный сервис, при котором клиенты подключаются к серверу.Любой подключенный клиент может выполнить операцию службы BookAdded.Когда это происходит, сервер должен вызвать обратный вызов на всех подключенных клиентах, чтобы уведомить их об изменении.

Кажется, что обратный вызов работает нормально, за исключением того, что для операции обратного вызова необходимо выполнить что-то в потоке пользовательского интерфейса, используя1004 *.

В моем случае 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();
    }

Ответы [ 2 ]

3 голосов
/ 03 апреля 2011

Я подозреваю, что происходит то, что поток пользовательского интерфейса все еще заблокирован при исходном вызове на сервер, который еще не завершен. Я думаю, что если вы измените режим параллелизма на клиенте для повторного входа, он может работать. . Что вам нужно сделать, это установить [CallbackBehavior (UseSynchronizationContext = false)] для обратного вызова.

Эта статья достаточно хорошо объясняет эту проблему.

GJ

0 голосов
/ 20 июля 2012

Я думаю, что столкнулся с подобной проблемой с вашей. Я решил это с новым потоком, чтобы вызвать Dispatcher.beginInvoke. Как я понимаю, поток пользовательского интерфейса отправляет запрос в службу, служба будет вызывать контракт обратного вызова, который реализуется в вашем клиенте во время операции службы. Таким образом, если в операции обратного вызова он вызывает управление потоком пользовательского интерфейса, который ожидает ответа от операции службы. Вот почему клиент находится в тупике. Так что вы можете попробовать код ниже: Thread th=new Thread(new ThreadStart(()=>{Console.WriteLine("Callback thread");<br> theDispatcher.BeginInvoke(new Action(() => { Console.WriteLine("Dispatcher thread"); }));<br> })); th.Start();

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...