问题
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?
Reuest-reply operation and one-way call back method for the progress messaages from the service within the operation?
Blocking (request-reply) operation and blocking (sync) progress messages from service
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.
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:
[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);
}
}
来源:https://stackoverflow.com/questions/7865537/wcf-informing-about-the-progress-to-client-can-i-use-one-way-call-back-method