0

I have a problem updating my WPF UI while executing a WCF service which send messages to client after each action executed on service. I use WSDualHttpBinding. The same implementation works perfectly when I display a message box for each message came from the service. But this doesn't work on updating UI.

PS: I use MVVM pattern and Caliburn.micro My implementation simplified:

1- Interfaces:

    public interface IMyContractCallback
{
    [OperationContract]
    void OnCallback();
}


 [ServiceContract(CallbackContract = typeof(IMyContractCallback))]
public interface IMyContract
{
    [OperationContract]
    void DoSomething();
}

2- Service:

[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Reentrant)]
public class MyService : IMyContract
{
    public void DoSomething()
    {
        DoJob1();
        var callbackChannel = OperationContext.Current.GetCallbackChannel<IMyContractCallback>();
        callbackChannel.OnCallback();
        DoJob2();

    }
}

3- Client:

  • Callback implementation:

public delegate void ClientNotifiedEventHandler(object sender, ClientNotifiedEventArgs e);

 public class ClientNotifiedEventArgs : EventArgs
    {
                private readonly string _message;
                public string Message { get { return _message; } }

                public ClientNotifiedEventArgs(string message)
                {
                    this._message = message;
                }
    }



    [CallbackBehavior(ConcurrencyMode = ConcurrencyMode.Reentrant, UseSynchronizationContext = false)]
        public class MyCallbackClient : IMyContractCallback
        {
public event ClientNotifiedEventHandler ClientNotified;
            public void OnCallback()
            {
                 if (ClientNotified != null)
                        {
                            ClientNotified(this, new ClientNotifiedEventArgs(log));
                        }
            }
        }
  1. ViewModel implementation:

    Public class MyViewModel {

        private string _message = "Loading..";
    
        public string MessageLog
    
        {
            get { return _message; }
            set
            {
                _message = value;
                NotifyOfPropertyChange(() => MessageLog);
            }
        }
    
        public void DoTheJob()
        {
            var callback = new DbLoaderCallback();
            callback.ClientNotified += Callback_ClientNotified;
            var context = new InstanceContext(callback);
            using (var serviceClient = new MyService(context))
            {
                serviceClient.DoSomething();
            }
        }
    
        private void Callback_ClientNotified(object sender, ClientNotifiedEventArgs e)
        {
            MessageLog += " \n";
            MessageLog += e.Message;
    
        }    
    

    }

Here, when the execution come to callbackChannel.OnCallback(); (on MyService), It goes to client, on MyViewModel, when we come to NotifyOfPropertyChange(() => MessageLog); it doesn't continue the execution. So DoJob2() did never executed.

Did any one see what's the problem exactly? Thanks in advance

1 Answers1

0

You have UseSynchronizationContext = false specified for your callback, which means that all callbacks are called on a thread pool. UI does not allow to update itself from any thread but dispatcher one. So, you need to marshal update of MessageLog property onto the dispatcher thread. See this answer.

Community
  • 1
  • 1
Igor Labutin
  • 1,406
  • 10
  • 10