I have a WCF webservice using the WebServiceHost class.
new WebServiceHost(typeof(MyServiceClass));
If I use a blocking call like Thread.Sleep (just an example) in one of my webservice methods and i call this method the whole service is not usable while the blocking call is active.
Is that normal behaviour or is there an error somewhere in my configuration or usage?
What's the InstanceContextMode and ConcurrencyMode settings on your service? If it's set to Single then there's only one instance of your service and all the calls are queued so if you put the service thread to sleep it will block all subsequent calls.
For example:
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single,
ConcurrencyMode = ConcurrencyMode.Single)]
public class MyService : IMyService
{
}
Ok, I got it. If you start the service in a windows forms GUI thread you can add
UseSynchronizationContext = false
to the ServiceBehavior and the requests get handled in parallel. :)
Related
I am currently developing a REST Service where one of the methods is a long running task (named CalculatePrimeOneWay). Its definition is
[OperationContract(IsOneWay = true)]
[WebInvoke(Method = "POST", UriTemplate = "primeoneway/{jobnumber}")]
void CalculatePrimeOneWay(string jobnumber, Prime prime);
As there is no callback capability with a REST Service, I thought about implementing a kind of polling method to obtain status information. This polling method is defined as
[OperationContract]
[WebGet(UriTemplate = "poll/{jobnumber}")]
Job GetJobStatus(string jobnumber);
I write status information into a MS SQL table.
I start my client and invoke the CalculatePrimeOneWay Method. Subsequent calls to GetJobStatus return a WebException with Protocol Error, Status Code 400 and Status Description Bad Request.
However, if CalculatePrimeOneWay is finished and I then invoke GetJobStatus, all works perfectly fine.
Why am I unable to call GetJobStatus while CalculatePrimeOneWay is still running?
What other solutions would be possible for my scenario of a long runnning task and a polling mechanism?
Thanks
The behaviour you're getting may be a result of one or both of two things:
You are running the service with per-session or singleton instancing
You are re-using the same client channel to make the polling call as you did to make the one-way call.
You should have the service configured to per-call instancing and make the polling call on a new client channel instance.
I have now explicitly defined the service PerCall. For each call from
the client I get a new HttpWebRequest object and after the call, I
close the web response object. The behaviour is still the same
OK try replacing
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
with
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall,
ConcurrencyMode = ConcurrencyMode.Multiple,
UseSynchronizationContext = false)]
I am using IIS Express out of my VisualStudio
OK - the reason you are getting this behaviour is because you're hosting using the Visual Studio which uses the cassini web server. This does not support concurrency when processing requests. See posts here and here.
Try hosting the service temporarily in a console app and this problem will be resolved.
I develop WCF-service with duplex mode and use nettcpbinding. I use .NET 4.5. I have only one client and only one server and there is a lot of logic between its. The client always the first begins communication with the server. I want that server can call client functions outside WCF-service class. I try to use duplex mode for this purpose.
This is my WCF-service:
[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Single, InstanceContextMode = InstanceContextMode.Single)]
public class Service : IService
{
...
public IServiceCallback Callback
{
get
{
return OperationContext.Current.GetCallbackChannel<IServiceCallback>();
}
}
}
I have no problem when I call my callback within OperationContract functions of my service:
Callback.foo();
But when I try to call it outside class Service for example:
service = new Service();
service.Callback.foo();
I got NullReferenceException of OperationContext.Current. I found a lot of information about the similar problems on the SO and other resources but it can't help to decide my problem.
Are there any solutions of my issue or may be workarounds for calling of callback? At the moment I plan to create one more WCF-service for my purpose but I feel that this is bad solution. Thanks for attention.
OperationContext.Current has a meaning only when it runs from the same thread that handles the current client request. You did not specify where exactly you calls this from.
I have a WCF service that is hosted by a windows service. I can't figure out how to inform the windows service when a client connects to the WCF service. Basically all I have in the windows service to start the WCF service is this:
private ServiceHost sHost;
WCF.WCFService wcfService = new WCF.WCFService();
sHost = new ServiceHost(wcfService);
sHost.Open();
I am able to call methods in the WCF service with the windows service using the wcfService object. Is there some way to have some kind of event that would fire when a client connects to WCF service?
The service runs as an object which is instantiated according to the ServiceBehaviourAttribute property InstanceContextMode
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
public class MyService : IMyService
{
// ...
The values for InstanceContextMode are
Single - a single instance of the service runs for all sessions and calls
PerSession - an instance of the service runs for each session (i.e. each client)
PerCall - an instance of the service is instantiated for each call, even from a single client
The default value is PerSession, and this makes sense for most scenarios. Assuming you're using PerSession, you can put whatever 'connect logic' you like inside the constructor for the service.
// you don't need to specify PerSession as it is default, but I have for clarity
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)]
public class MyService : IMyService
{
public MyService()
{
// constructor will be called for each new client session
// eg fire an Event, log a new client has connected, etc
}
// ...
}
You need to be careful running code in the constructor, because the service will not be available until the constructor has completed. If you want to do anything that may take time, fire an event or send a thread to perform that work.
I found the best answer here: Subscribe to events within a WCF service
As suspected you can create an event handler in the WCF service that can be picked up by the host.
I have two services, one that calls another. Both are marked as singletons as follows:
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single,
ConcurrencyMode = ConcurrencyMode.Multiple)]
public class Service : IService
And I set these up with a ServiceHost as follows:
ServiceHost serviceHost = new ServiceHost(singletonElement);
serviceHost.Open();
When the parent service tries to call the child service on the same machine, the parent service hangs, waiting for the child service.
I'm already considering moving away from the singleton model, but is there anything wrong with my approach? Is there an explanation for this behavior and a way out of it?
The parent service hangs it because might be becoz the child service method is taking too long. If it takes long time to return call it asyncronously or make child servcie method IsOneWayo=True in the OpearationContract arrtribute.
One way service is Fire & Forget kind of call it does not return any value.
The problem was that I was hosting within a WPF application and did not set UseSynchronizationContext to false. This makes the WCF service host in the UI thread, thus causing a deadlock when you have one service (on the UI thread) calling another service (also on a UI thread).
I'm trying to program a client server based on the callback infrastructure provided by WCF but it isn't working asynchronously.
My client connects to the server calling a login method, where I save the clients callback channel by doing
MyCallback callback =
OperationContext.Current.GetCallbackChannel<MyNamespace.MyCallback>()
After that the server does some processing and uses the callback object to communicate with the client.
All this works, the problem resides on the fact that even though I've set the method in the OperationContract as IsOneWay=true, the server still hangs when doing the call to the client.
I've tested this by launching the server for debug in the Visual Studio, detaching it, launching the client, calling the above mentioned login method, putting a break point in the implemented callback method of the client, and making the server send a response to the client. The server stops doing what it's supposed to do, waiting for the response of the client.
Any help is appreciated.
The trick is, to call the callback asynchronously from the server. Look at this:
[OperationContract(IsOneWay = true, AsyncPattern = true)]
IAsyncResult BeginOnMessageReceived(LiveDataMessage message, AsyncCallback acb, object state);
void EndOnMessageReceived(IAsyncResult iar);
I think the sollution to your problem is to properly set the 'ConcurecyMode' and 'Instance ContextMode' attributes for your service. To do that you must decorate your service declaration with those attributes as shown in the exemple below:
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Reentrant)]
public class SubscriberService: ISubscriberServiceContract
{...}
InstanceContextMode.Single builds your service as a Singleton object so there is only one instance of your service running for all clients;
ConcurencyMode.Reentrant or ConcurencyMode.Multiple enables multithreaded work for the service instance. For 'Multiple' you must take care of thread syncronization in your service.
Did you try to set
[CallbackBehavior(UseSynchronizationContext = false)]
on the client side object implementing the callback interface ?