Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/wcf/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/ssh/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
WCF-向客户端通知进度(我可以在请求/回复操作中使用单向回调方法吗)_Wcf_Wcf Client - Fatal编程技术网

WCF-向客户端通知进度(我可以在请求/回复操作中使用单向回调方法吗)

WCF-向客户端通知进度(我可以在请求/回复操作中使用单向回调方法吗),wcf,wcf-client,Wcf,Wcf Client,我的合同具有执行多个任务的请求-答复操作。因此,我想向客户告知操作的进度,因为这是一个长期运行的操作。所以双工是理想的选择,因为我可以使用回调方法。但我的操作在操作结束时返回结果。那么,解决这个问题的建议是什么 是否为操作中服务的进度消息重新请求回复操作和单向回调方法 阻止(请求-应答)操作和阻止(同步)来自服务的进度消息 回调方法是否会使用相同的通道,我的阻塞(请求-应答)方法是否会假定其结果 如果是,我应该异步执行服务操作吗 回调方法将出现在另一个工作线程中,还是返回给给定实例上下文的同

我的合同具有执行多个任务的请求-答复操作。因此,我想向客户告知操作的进度,因为这是一个长期运行的操作。所以双工是理想的选择,因为我可以使用回调方法。但我的操作在操作结束时返回结果。那么,解决这个问题的建议是什么

  • 是否为操作中服务的进度消息重新请求回复操作和单向回调方法

  • 阻止(请求-应答)操作和阻止(同步)来自服务的进度消息

  • 回调方法是否会使用相同的通道,我的阻塞(请求-应答)方法是否会假定其结果

    • 如果是,我应该异步执行服务操作吗
  • 回调方法将出现在另一个工作线程中,还是返回给给定实例上下文的同一线程

  • 我认为阻塞服务操作和阻塞进程消息的回调方法(如果它可以在另一个线程上返回)将是理想且简单的解决方案

    但我不确定WCF为我提供了多少现成的服务


    换句话说,我想做一些类似于下面代码(psuedo)的事情。它起作用了。你认为这种方法有什么问题吗?(想法是在阻塞调用中调用回调方法。服务在多个concurencymode中运行。因此我声明callback UseSynchronizationContext=false)以避免死锁。下面的方法有什么问题吗

    [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();
               ...
                   ...
         }
    }    
    

    即使我将UseSynchronizationContext设置为true,WCF仍在工作线程本身中调用report方法。看起来我不需要把它设为false。因为我正在调用另一个线程中的操作,所以它仅对UI线程有意义吗?

    [ServiceContract(CallbackContract=typeof(IsSubscriber))]
    
    [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));
            }
    
        }
    }
    
    公共接口ijob处理器 { [运营合同(IsOneWay=true)] void ProcessJob(); } [服务合同] 公共接口ISubscriber { //这将是服务器用来通知客户机状态的操作。 [经营合同] void UpdateStatus(字符串状态消息); } 班级计划 { 静态void Main(字符串[]参数) { ServiceHost主机=新ServiceHost(类型化(JobProcessor)),新Uri[]{new Uri(“net。tcp://localhost:10000") }); AddServiceEndpoint(typeof(IJobProcessor),new NetTcpBinding(),“jobprocessor”); host.Open(); Console.WriteLine(“服务器正在运行。按enter键退出!”); Console.Read(); } } [ServiceBehavior(ConcurrencyMode=ConcurrencyMode.Reentrant)] 公共类JobProcessor:IJobProcessor { public void ProcessJob() { ISubscriber subscriber=OperationContext.Current.GetCallbackChannel(); 对于(int i=0;i<5;i++) { 线程。睡眠(1000*10); subscriber.UpdateStatus(String.Format(“{0}%完成)”,(i+1)*20); } } }
    //客户看起来像这样

    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);
        }
    }
    
    类程序
    {
    静态void Main(字符串[]参数)
    {
    var proxy=DuplexChannelFactory.CreateChannel(新InstanceContext(新订户())、新NetTcpBinding()、新EndpointAddress(“网络”)。tcp://localhost:10000/jobprocessor"));
    proxy.ProcessJob();
    Console.Write(“客户正在进行其他工作…”);
    Console.Read();
    }
    }
    公共类订户:ISubscriber
    {
    公共无效更新状态(字符串状态消息)
    {
    Console.WriteLine(状态消息);
    }
    }
    
    [ServiceContract(CallbackContract=typeof(ISubscriber))]
    公共接口ijob处理器
    {
    [运营合同(IsOneWay=true)]
    void ProcessJob();
    }
    [服务合同]
    公共接口ISubscriber
    {
    //这将是服务器用来通知客户机状态的操作。
    [经营合同]
    void UpdateStatus(字符串状态消息);
    }
    班级计划
    {
    静态void Main(字符串[]参数)
    {
    ServiceHost主机=新ServiceHost(类型化(JobProcessor)),新Uri[]{new Uri(“net。tcp://localhost:10000") });
    AddServiceEndpoint(typeof(IJobProcessor),new NetTcpBinding(),“jobprocessor”);
    host.Open();
    Console.WriteLine(“服务器正在运行。按enter键退出!”);
    Console.Read();
    }
    }
    [ServiceBehavior(ConcurrencyMode=ConcurrencyMode.Reentrant)]
    公共类JobProcessor:IJobProcessor
    {
    public void ProcessJob()
    {
    ISubscriber subscriber=OperationContext.Current.GetCallbackChannel();
    对于(int i=0;i<5;i++)
    {
    线程。睡眠(1000*10);
    subscriber.UpdateStatus(String.Format(“{0}%完成)”,(i+1)*20);
    }
    }
    }
    
    //客户看起来像这样

    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);
        }
    }
    
    类程序
    {
    静态void Main(字符串[]参数)
    {
    var proxy=DuplexChannelFactory.CreateChannel(新InstanceContext(新订户())、新NetTcpBinding()、新EndpointAddress(“网络”)。tcp://localhost:10000/jobprocessor"));
    proxy.ProcessJob();
    Console.Write(“客户正在进行其他工作…”);
    Console.Read();
    }
    }
    公共类订户:ISubscriber
    {
    公共无效更新状态(字符串状态消息)
    {
    Console.WriteLine(状态消息);
    }
    }
    
    谢谢你,普拉桑斯。但挑战在于在请求-应答操作中调用回调方法,并最终返回结果。服务以persession实例模式运行,具有多个并发性。因此,我将callback instacne声明为UseSynchronizationContext=false,这样它就不会使用与调用者相同的线程。我还将Concurence模式声明为multiple,以获得有效的吞吐量。您是否看到了这方面的任何问题?因此,当您的客户端调用长时间运行的操作时,如果调用线程得到b,则没有问题