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