Regardind this solution Using the CCR with ASynchronous WCF Service
Why do you need to do this :
ThreadPool.QueueUserWorkItem(s => callback(this));
instead of just calling callback(this) ?
Isn't QueueUserWorkItem going to use yet another thread ?
"callback" is a method that needs to be provided as an input parameter to BeginGetAccount. In the answer it doesn't specify the "callback" method so there is no way to know if it makes use of a new thread or not and therefore it does make sense to put the "callback" method on a seperate thread in Complete.
If you could guarantee "callback" created its own thread then you wouldn't need to create one in the Complete method.
Related
I have WCF service which sends messages to its clients. I would like to call callback methods asynchronously. I have read this answer:
WCF asynchronous callback
But there is one problem. When I am generating IMyServiceCallback from WebServiceReference it contains both synchronous and asynchronous methods (while on the service side there is callback contract with only asynchronous methods - BeginCallbackMethod and EndCallbackMethod). What is more when I call from MyService to calback BeginCallbackMethod, on the client side (in callback implementation) it is using synchronous CallbackMethod. The question is why? Is there any way to configure it?
By default WCF will call the synchronous version of an operation if both sync and async are present; I don't know how (or if) you can change that logic, but one thing you can do is to simply remove the synchronous method from the generated callback interface. The callback code should continue to work, and it will use the asynchronous implementation instead. You can also just remove the [OperationContract] attribute from the synchronous version, to the same effect.
I have a WCF restful service and it works correctly, the problem is that the service expose a method "Calculate" and it may take several minutes to complete the calculation, and since REST is a stateless method, I'm running out of ideas !
should I maintain the session ?
how can I do a callback ?
10 minutes waiting for a response in a website is not convenient, but I have to find a solution.
PS: the service MUST be restful, and I cant reduce the calculation time.
I asked about your clients because if they were .Net only, you could implement the async programming model, but since they aren't...
You can do something like in this post - WCF Rest Asynchronous Calling Methods
Basically your method will spawn an additional thread to do the actual calculation work, and return some sort of token to the calling client immediately in the main thread. The client can then use this token in a polling method to check if the calculation is complete.
You can create a one-way WebMethod to submit the intial calculation request. Inside your calculation code, you need to update a database table or similiar with progress, either percentage or completion.
You will then need to create an additional 'Polling' method that you can use to check the status, using the previous table.
When your calculation method marks it as complete, you can then call a final 'GetResults' method which will do just that.
We do something similiar for large file imports that are submitted via web services and it works very well.
Some info;
http://msdn.microsoft.com/en-us/library/system.web.services.protocols.soapdocumentmethodattribute.oneway(v=vs.71).aspx
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.
I want to call a web service from another web service in a non-blocking way. I've implemented this by using BackgroundWorker. But, I'm not sure whether this is the best way to do.
Scenario:
I call a web service Service_A which performs certain task & has to inform another web service Service_B about the changes made. I call the Service_B's one-way function NotifyUpdates for handling the updates. Service_A doesn't waits for Service_B's response & continues with its task. The response from the Service_B is logged in the background.
My question is, what is the best way to do it?
Thanks.
BackgroundWorker is purposed for UI use, and I don't think it's the best way to use it here.
If you are using .Net 4 better to use Task
var t = Task.Factory.StartNew(() => DoServiceBCall());
If not,use ThreadPool.QueueUserWorkItem or Thread
ThreadPool.QueueUserWorkItem(new WaitCallback(DoServiceBCall));
Hope this helps
First of all, based on your scenario, if call to Service B is one way, Service A will not receive any response from Service-B except Http Status code (if call to service-B is on Http).
I'd call Service-B asynchronously to keep the things and code simple.
HTH,
Amit
I'm wondering if there's any way to force a client to call a specific method on a duplex WCF service. My situation is this, my service implementation is going to keep a collection of subscribers. The problem with this approach is, what if the client doesn't call Subscribe()? I was thinking that in my client interface, I'd have a method called Subscribe, but that doesn't get me anywhere since the code to actually call the service can still be left out of the implementation. Is this possible?
Thanks!
Duplex WCF service uses WCF session so you can mark your Subscribe method with:
[OperationContract(IsInitiating=true)]
void Subscribe();
All other methods will have IsInitiating=false and because of that Subscribe method will have to be the first method called to start a new session. You can also have special method with IsTerminating=true to close the session.