Asynchronous WCF - wcf

I am trying to create a WCF service that supports asynchronous calls. I followed all samples and tutorials I could find, and all of them have the customary pattern of one synchronous method, and the async Begin and End such as:
[OperationContract(AsyncPattern = false)]
string GetData(int value);
[OperationContract(AsyncPattern = true)]
IAsyncResult BeginGetData(int value, AsyncCallback callback, object asyncState);
string EndGetData(IAsyncResult result);
However, only the synchronous GetData gets called, no matter what I do on the client side. Fiddler tells me that the message is always the same:
<s:Envelope
xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"><s:Body><GetData
xmlns="http://tempuri.org/"><value>0</value></GetData></s:Body></s:Envelope>
When I remove the synchronous GetData interface, the async method now is properly called.
Is this normal behavior? Is there anything else I should do to support sync and async versions of a method?

This is a common misconception. You assume that you need to make the server asynchronous in order for the client to be able to make async calls. This is not true. Server and client are 100% independent. They are separated by a binary wire protocol.
The message that you see in Fiddler is always the same because SOAP does not know anything about sync or async. At the SOAP level your decision does not manifest itself. For that reason the client cannot observe your server-side decision, either.
This means you can just make the server synchronous in still have a truely async client, or the other way around.
In any case, you should only implement one pattern on the server: Either sync or async. Never both. Get rid of one of your implementations. From a functional standpoint it doesn't matter which one stays.
I'm pulling up important information from the comments here:
It is hard to fit an explanation about when to use server-side async
into this comment box. In short, don't use it on the server by
default. Use it if special circumstances make it attractive or
necessary.
On a meta-level let me point out that async IO has become
a fad that should not be followed lightly. The community is in a very
unfortunate state of misinformation about this right now.

Related

WCF Web Service and TPL Task.Run

Suppose I have a method, which does not require a response, for example:
[ServiceContract]
public interface IWCFTestService
{
[OperationContract]
void ReceiveSomeData(MyDto someDtoObj);
}
Now, inside the actual service implementation, I can write:
public void ReceiveSomeData(MyDto receivedRequest)
{
Task.Run( () => OtherProjectOtherClass.DoWhateverYouWant(receivedRequest) )
//... because I am outta here as fast as possible
}
I assume the caller will get a 200-OK all the time; Note also that I have not written any task async/await inside the WCF method itself.
Is it acceptable to use TPL inside WCF this way, any gotchas?
Note: I am not concerned with business rules, I am more concerned whether it is technically acceptable for WCF/TPL to interact this way, will I run into (technical) trouble?
There are a couple of things that you have to take in consideration.
Callers won't be notitified when the task is actually completed, and if it does, whether it did so with a failure (an unhandled exception for example) or not.
When the process hosting the service stops, your tasks may not be completed yet and unless you keep a reference to them you won't be able to wait for them to finish.
If an unhandled exception occurs in OtherProjectOtherClass.DoWhateverYouWant(receivedRequest) you won't be signalled. So make sure the whole body is contained in a try..catch and apply some logging or take other measures.
If a lot of requests are made and the tasks take a long time to complete you can run out of threads in the threadpool. If so, use a dedicated thread as Task.Run grabs one from the pool.
I do wonder, what is happening inside OtherProjectOtherClass.DoWhateverYouWant(receivedRequest)? Is it CPU intensive or more I/O related? If it is I/O intensive, rewrite it to a Task based method instead of using Task.Run.
I can't tell if these issues are really problems for you but keep it in mind.

WCF Asynch pattern - Really required?

I have created one WCF service which performs a lengthy operation asynchronously using Asynch pattern. I have referred to below link to implement BeginAddNumbers and EndAddNumbers methods in the ServiceContract.
http://aspalliance.com/1335_Asynchronous_Pattern_in_Windows_Communication_Foundation.5
Everything is working fine. But I dont understand why we require this approach?
Even though its asynchronous operation on server, client will still blocked and we
have to invoke this operation asynchornously on client as well.
So instead of implementing operation asynchronously on server it's always
better to invoke operation asynchronously on client side to have responsive UI.
Can anyone help me to understand concept of implementing asynchronous operation on server side? Any practical example where I need to play around AsyncPattern=true in conjunction with OperationContract ?
Adding client code. Client is implemented using WPF application
private void button1_Click(object sender, RoutedEventArgs e)
{
MathOperationClient c = new MathOperationClient();
Task t = new Task(new Action(() =>
{
///Even if AddNumbers is is implemented as asynchronous operation
///second call to AddNumbers get chance only after completing below
///call.
///Note: AddNumbers method takes 10 sec to execute
int nResult = c.AddNumbers(2, 3);
this.Dispatcher.BeginInvoke(new Action(()=>{
label1.Content = nResult.ToString();
})
, null);
}));
t.Start();
Task t1 = new Task(new Action(() =>
{
///Below method is invoked only after executing first call ( above call with parameters 2 and 3 )
///in other words below call is blocked for 10 seconds.
///So what is advantage of implementing asynchronous AddNumbers method on server side?
int result = c.AddNumbers(5,5);
this.Dispatcher.BeginInvoke(new Action(() =>
{
label2.Content = result.ToString();
})
, null);
}));
t1.Start();
}
Thanks, Hemant
this post has some information.
in general:
In case of WCF, the realproxy is of type System.ServiceModel.Channels.ServiceChannelProxy. This proxy implementation calls service method synchronously even if we call it using BeginInvoke.
WCF only issues asynchronous calls if the method that is called on a proxy begins with BeginXXX() and is decorated with [OperationContract(AsyncPattern=true)] attribute.
I like the idea to implement this server side; and clearly indicate this by naming the operation accordingly. After all, if a call is asynchronous in nature, why give the client the choice?
Another reason is scalability: doing it server-side decouples the request from the WCF dispatcher thread. This means that WCF threads will not be blocked.
See here for an example.
You could even decide to make it a one way call; and have the client poll at regular intervals; which is, in fact, my favorite approach.

Using TAP progress reporting in a WCF service

I (new to WCF) am writing a WCF service that acquires and analyzes an X-ray spectrum - i.e. it is a long-running process, sometimes several minutes. Naturally, this begs for asynchronous calls so, using wsDualHttpBinding and defining the following in my ServiceContract
[ServiceContract(Namespace="--removed--",
SessionMode=SessionMode.Required, CallbackContract=typeof(IAnalysisSubscriber))]
public interface IAnalysisController
{
// Simplified - removed other declarations for clarity
[OperationContract]
Task<Measurement> StartMeasurement(MeasurementRequest request);
}
And the (simplified) implementation has
async public Task<Measurement> StartMeasurement(MeasurementRequest request)
{
m_meas = m_config.GetMeasurement(request);
Spectrum sp = await m_mca.Acquire(m_meas.AcquisitionTime, null);
UpdateSpectrum(m_meas, sp);
return m_meas;
}
private void McaProgress(Spectrum sp)
{
m_client.ReportProgress(sp);
}
Where m_client is the callback object obtained from m_client = OperationContext.Current.GetCallbackChannel(); in the "Connect" method - called when the WCF client first connects. This works as long as I don't use progress reporting, but as soon as I add progress reporting by changing the "null" in the m_mca.Acquire() method to "new Progress(McaProgress)", on the first progress report, the client generates an error "The server did not provide a meaningful reply; this might be caused by a contract mismatch..."
I understand the client is probably awaiting a particular reply of a Task rather than having a callback made into it, but how do I implement this type of progress reporting with WCF? I would like the client to be able to see the live spectrum as it is generated and get an estimate of the time remaining to complete the spectrum acquisition. Any help or pointers to where someone has implemented this type of progress reporting with WCF is much appreciated (I've been searching but find mostly references to EAP or APM and WCF and not much related to TAP).
Thanks, Dave
Progress<T> wasn't really meant for use in WCF. It was designed for UI apps, and may behave oddly depending on your host (e.g., ASP.NET vs self-hosted).
I would recommend writing a simple IProgress<T> implementation that just called IAnalysisSubscriber.ReportProgress directly. Also make sure that IAnalysisSubscriber.ReportProgress has OperationContract.IsOneWay set to true.

Modeling Client Context in WCF Web API with MEF

I need to extract several header values at the start of each request and place them into a ClientContext object that can be injected into my application code by MEF. I am using Preview 5 of the WCF Web API and don't see a way to do this.
In 'standard' WCF, I would create a class that implements IExtension<OperationContext> and have the following property to wire it all together:
[Export(typeof(IClientContext)]
[PartCreationPolicy(CreationPolicy.NonShared)]
public static ClientContextExtension Current
{
get
{
var operationContext = OperationContext.Current;
if (operationContext == null)
return null;
var extension = operationContext.Extensions.Find<ClientContextExtension>();
if (extension == null)
{
extension = new ClientContextExtension();
operationContext.Extensions.Add(extension);
}
return extension;
}
}
A custom DelegatingHandler calls ClientContextExtension.Current and sets the properties from the header values. Unfortunately, with WCF Web API, OperationContext.Current is always null!
I cannot figure out a way to make this work with the Web API. Any help is appreciated!!!
I've come up with a working solution but remain open to other options. First, some rationale behind the original approach...
Because WCF uses thread pooling, anything based on a per-thread model may (and will) have a lifetime that extends beyond an individual request. I needed a way to store client context information pulled from the HTTP headers for each request as the information will be different each time. This means I can't persist the context information per-thread because the thread will be re-used.
Or can I?
The flaw in my logic was that thread re-use was the problem. In reality, each thread is only every servicing a single request at one time thereby making any information in that thread isolated to that request. Therefore, all I need to do is make sure that the information is relavent to that request and my problem is solved.
My solution was to refactor the Current property to reference a private static field marked with the [ThreadStatic()] attribute, ensuring that each instance was specific to the thread. Then, in my DelegatingHandler, which executes for each request, I reset the properties of the object for that request. Subsequent calls to Current during that request return the request-specific information and the next request handled by the thread gets updated in the DelegatingHandler so as far as my other code is concerned, the context is per-request.
Not perfect, but it at least gets me up and running for the moment. As I said, I am open to other solutions.
UPDATE
Upon closer inspection, this solution is not working as there is no thread affinity between the DelegatingHandler and the service code that is making use of the context object. As a result, sometimes my call to retrieve the ThreadStatic object works as expected but on other occasions I get a new instance because the code is operating on a different thread than the handler.
So, disregard this solution. Back to the drawing board.
UPDATE TO MY UPDATE
After discussing my problem with Glenn Block, it turns out that it is just a matter of making sure the context is set on the same thread the request handler (the service) is executing. The solution is to use an HttpOperationHandler instead of a MessageHandler.
According to Glenn, message handlers operate asynchronously which means they could execute on a different thread from the request handler (service) so we should never do anything in a message handler that requires thread affinity. On the other hand, operation handlers run synchronously on the same thread as the request handler, therefore we can rely on thread affinity.
So, I simply moved my code from a MessageHandler to an HttpOperationHandler and have the desired results.
You can read a full explanation here: http://sonofpirate.blogspot.com/2011/11/modeling-client-context-in-wcf-web-api.html
You can try to use a
HttpOperationHandler<HttpRequestMessage, HttpRequestMessage>
There you should be able to access the headers.

Serializing Delegates in WCF Using a Surrogate?

I have an idea, but I need help implementing it.
WCF does not support delegates in its contracts.
Instead it has a cumbersome callback contracts mechanism, and I'm looking for a way to overcome this limitation.
I thought about using a IDataContractSurrogate to replace each delegate in the contract with a token that will be serialized to the remote endpoint. There, the token will be deserialized into a generated delegate. This generated delegate will send a generic callback message which encapsulates all the arguments (that the delegate was invoked with).
The generic callback message will reach the first endpoint, and there the original delegate would be invoked with the arguments.
Here is the purposed (simplified) sequence:
A calls B-proxy.Foo(callback)
callback is serialized through a DelegateSurrogate.
The DelegateSurrogate stores the delegate in a dedicated delegate storage and replaces it with a token
The message arrives to B's endpoint
the token is deserialized through a DelegateSurrogate
The DelegateSurrogate constructs a generated delegate
B.Foo(generatedCallback) is invoked
Later, B is invoking generatedCallback(args)
generatedCallback(args) calls a dedicated generic contract on A's endpoint: CallbackContract-proxy.GenericCallback(args)
CallbackContract.GenericCallback(args) is invoked on A's endpoint
The original callback is retrieved from the storage and is invoked: callback(args)
I have already implemented this previously using service bus (NServiceBus), but I want to adapt the idea to WCF and I'm having hard time. I know how to implement steps 3,6,9 and 11. I don't know yet how to wire everything in WCF - especially the surrogate part.
That's it - I hope my question made sense, and that the collective wisdom here will be able to help me build this up.
Here's a sample usage for my desired solution:
// client side
remoteSvc.GetEmployeeById(17, emp =>
{
employees.Add(emp);
logger.log("Result received");
});
// server side
public void GetEmployeeById(int id, Action<Employee> callback)
{
var emp = getEmpFromDb(id);
callback(emp);
}
Actually, in this scenario I would look into the Expression API. Unlike a delegate, an Expression can be deconstructed at runtime. You can't serialize them by default, but a lot of work has been done in that space. It is also a bit like what a lot of LINQ providers do in the background, for example WCF Data Services.
Of course, another approach is simply to use a lambda expression as the hook for RPC, which is what I describe here. The code that implements this is freely available in the protobuf-net tree. You could customize this by using an attribute to associate your token with the method, and obtain the attribute from the MethodInfo.
IMO, the problem with delegates is that they are too tightly coupled to the implementation, so you can't have different implementations at each end (which is a common requirement).
Expressions have the advantage that lambdas still support intellisense etc, so you can do things like:
client.Invoke(svc => svc.Foo(123, "abc"));
and from that obtain Foo (the MethodInfo), 123 and "abc" separately, including captured variables, ref/out, etc. It all works.