WCF - Informing about the progress to client (Can

2019-08-06 02:36发布

My contract has request-reply operation which performs multiple tasks. So I would like to inform about the progress of the operation to the client as its a long running operation. So Duplex is the ideal choice as I can use call back methods. But my operation returns results at the end of the operations. So what is the recommendation to solve this problem?

  1. Reuest-reply operation and one-way call back method for the progress messaages from the service within the operation?

  2. Blocking (request-reply) operation and blocking (sync) progress messages from service

  3. Will the call back method uses same channel, so will my blocking (request-reply) method assumes its its result?

    • If yes, should I perform my service operation asynchronously.
  4. Will the call back method will come in another worker thread or will be returned to the same thread which has given the instance context?

I think blocking service operation and blocking call back method for progress message (if it can return on another thread) will be ideal and easy solution.

But I am not sure how much WCF provides me out of box.


In Other words I want to do something similar to the below code(psuedo). Its working. Do you see any issues with this approach? (The idea is to calling a callback method within a blocking call. Service runs in multiple concurencymode. So i declared callback UseSynchronizationContext = false) to avoid deadlock.any issues are there with the below approach?

[ServiceContract(CallbackContract(typeof(IServiceCallback)]]
public interfact IService
{
     //A long (timetaken) request-reply operation
     string LonggggWork();
}

public interface IServiceCallback
{
     void Report(string msg);
}

[CallbackBehavior(ConcuerencyMode.Multiple, UseSynchronizationContext=false)]
public ClientCallback : IServiceCallback
{
public void Report(string msg)
{
     Console.WriteLine(msg);
}
}
[ServiceBehavior(ConcurencyMode.Multiple, InstanceMode.PerSession)]
publci Service : IService
{
     IServiceCallback callback = ....;
     public string LongggWork()
     {
          callback.Report("task1");
          task1();
          callback.Report("task2");
          task2();
           ...
               ...
     }
}    

Eventhough if i set it UseSynchronizationContext to true, WCF is invoking the report method in worker thread itself. So looks like I dont need to set it to false. Will it make sense only for UI thread becasue I am invoking operation already in a another thread?

1条回答
Evening l夕情丶
2楼-- · 2019-08-06 03:04
[ServiceContract(CallbackContract = typeof(ISubscriber))]
public interface IJobProcessor
{
    [OperationContract(IsOneWay = true)]
    void ProcessJob();
}



[ServiceContract]
public interface ISubscriber
{
    //This would be the operation using which the server would notify the client about the status.
    [OperationContract]
    void UpdateStatus(string statusMessage);
}

class Program
{
    static void Main(string[] args)
    {
        ServiceHost host = new ServiceHost(typeof(JobProcessor), new Uri[] { new Uri("net.tcp://localhost:10000") });
        host.AddServiceEndpoint(typeof(IJobProcessor), new NetTcpBinding(), "jobprocessor");
        host.Open();
        Console.WriteLine("Server  running. Press enter to quit!");
        Console.Read();
    }
}

[ServiceBehavior(ConcurrencyMode=ConcurrencyMode.Reentrant)]
public class JobProcessor : IJobProcessor
{
    public void ProcessJob()
    {
        ISubscriber subscriber = OperationContext.Current.GetCallbackChannel<ISubscriber>();
        for (int i = 0; i < 5; i++)
        {
            Thread.Sleep(1000 * 10);
            subscriber.UpdateStatus(String.Format("{0} % complete", (i + 1) * 20));
        }

    }
}

//Client would look something like this...

class Program
{
    static void Main(string[] args)
    {
        var proxy = DuplexChannelFactory<IJobProcessor>.CreateChannel(new InstanceContext(new Subscriber()), new NetTcpBinding(), new EndpointAddress("net.tcp://localhost:10000/jobprocessor"));
        proxy.ProcessJob();
        Console.Write("Client proceeding with other work...");
        Console.Read();
    }
}

public class Subscriber : ISubscriber
{
    public void UpdateStatus(string statusMessage)
    {
        Console.WriteLine(statusMessage);
    }
}
查看更多
登录 后发表回答