I am using a WCF service with my Silverlight 5 Application.
In one of my service calls I am doing a time consuming job. It takes 1 or 2 minutes to complete the event. I am not blocking the UI with busy indicators, so the user can still interact with the application.
The problem is when I do my first service call, it performs some time consuming operation. When the user loads some other, my second service call is not being processed until the first service is completed.
How can I perform the time consuming service call in separate thread to avoid other
calls waiting for this service completion?
WebService Code
[ServiceContract(Namespace = "")]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class TestService
{[OperationContract]
public bool PerformFileScan(int fileID)
{
//Time Consuming Process
}
}
cs
client.PerformFileScanAsnc(docId);
client.PerformFileScanCompleted += new EventHandler<.PerformFileScanCompletedEventArgs>(client_PerformFileScanCompleted);
You have two options:
Make your call asynchronous on the server side. You can use the TPL and just write something like Task.Factory.StartNew(...)
You can decorate your service implementation with the ServiceBehavior attribute and set the ConcurrencyMode to Multiple:
[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple)]
public class YourService
{
}
Then wcf will schedule calls to your service in parallel. But then you have to ensure that your service code is threadsafe!
Related
I have a WCF service (hosted in windows-service) and a client for it.
They interact as follows: client sends a request, service gets it and returns HTTP 200. Also client passes its address for the answer in the WS-Addressing header. For the moment that's all
After a few hours windows-service should send a result for that request. Client has a web-method that will get the result. So the question is: where should be a description (name of the method, its parameters) for the client's method that will get the result? Should the client expose its WSDL, or should I put that description in my WSDL (if it works that way)?
As I understand your scenario, you have two services, let's call them Service A (hosted in a Windows Service) and Service B. Service B sends a request to Service A (in other words, it's acting like a client) to have Service A start a long-running task of some sort.
When the task is complete, Service A needs to send the results to Service B. Since it's a long-running task, using a duplex binding would not be ideal. However, Service A could call a method exposed by Service B to send the results.
Something like this:
[ServiceContract]
public interface IServiceA
{
[OperationContract]
public void StartWork();
}
[ServiceContract]
public interface IServiceB
{
[OperationContract]
public void ReceiveResults(ResultData data);
}
where ResultData is some object containing the results (could be a simple type as well, this is simply for illustration). ServiceA's StartWork can return void (the response will still be sent to the client, since it's not marked as IsOneWay=true). Semi-pseduo code follows:
Start the task:
ServiceAClient client = new ServiceAClient();
client.Open();
client.StartWork();
client.Close();
Service A sends the results to Service B when the task is complete:
ResultData results = new ResultData();
ServiceBClient client = new ServiceBClient();
client.Open();
client.ReceiveResults(results);
client.Close();
In this case, the method to receive the results will be part of Service B's WSDL, as Service A will call that method.
I have a simple "Hello world" service based on basicHttpBinding. The service is hosted on a quad-core CPU.
When I run load tests only one core is occupied (95%), and the others three approximately 4-8%.
Why are the other cores not used for proccessing?
Setting ConcurrencyMode = ConcurrencyMode.Multiple didn't help.
Configure a ServiceBehavior for your service.
WCF uses ConcurrencyMode=ConcurrencyMode.Single by default. That mode runs all requests to your service in one thread.
With ConcurrencyMode.Single, WCF does not call again into the object
so long as the method is running. After the operation returns the
object can be called again.
One CPU core is used to run that thread.
Add the attribute below for your service to use all the CPUs:
[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple)]
Be careful with service state when you enable that mode. You may need to implement your own locking if you change state.
Check ConcurrencyMode Enumeration for more details.
Also make sure that your client makes four calls simultaneously (implement multi-threading in client). Without that you still will have sequential one-thread calls processing even if your server supports multi-threading.
Update after checking the code:
Your WCF method doesn't do any work that can load the CPU. Please replace your methods with some heavy CPU-using function (calculate hashes or factorial) and re-check.
[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple)]
public class HelloService : IHelloService
{
public string HelloWorld()
{
return "Hello world";
}
}
The API docs for BasicHttpBinding say this:
Any instance members are not guaranteed to be thread safe.
This implies that a single BasicHttpBinding instance should not be called from multiple threads in parallel, and therefore cannot be spread across multiple CPUs/CPU cores.
Imagine I have the following, standard WCF, code :
[ServiceContract]
interface ICustomerService {
[OperationContract]
Customer GetCustomer();
}
public ICustomerService {
public Customer GetCustomer()
{
return MyStore.WhatIsNeeded();
}
}
This is working well and allows me to distribute the service and the consuming code.
Is it possible (and is it a good idea) to completely bypass the WCF engine if working in a single box ?
In fact, I want the app to be able to run on farm servers, or on small single box servers.
To reduce WCF messaging cost, I'd like to have something like :
ICustomerService service = null;
if(singlebox)
{
service = new CustomerService(); // Direct instanciation of the service class. No WCF here ...
}
else
{
service = new CustomerServiceClient(); // Wcf client
}
var cust = service.GetCustomer();
If wrapped properly, can this technique reduce server charge ?
That won't work because the client will be attempting to access an endpoint for a service that no longer is exposing one. The WCF plumbing is required for the both the service and the client. For single box scenarios, look at the NetNamedPipeBinding which is the WCF plumbing done through the equivalent of shared memory.
This will surely reduce the overhead of WCF runtime. I'd create a factory class which will check if(singlebox) and new up the right implementation of ICustomerService.
I have a WCF application (vb) which works fine but when a user requests information while the server is doing a call to another user, everybody hangs!
When you configure your service, there are two things you need to configure:
InstanceContextMode - which determines how many service instances are created to service the client requests, try use PerCall/PerSession if possible as they allows for the most concurrency.
ConcurrencyMode - which determines if each service instance is single-threaded or multi-threaded.
Based on the information you've provided so far, I'd recommend changing these two settings and see if it solves your problem:
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall,
ConcurrencyMode = ConcurrencyMode.Multiple)]
public class MyService : IMyService { ... }
I put a blog post together of the things I learnt whilst doing some performance work on our WCF services a little while back, maybe it'd be of help:
http://theburningmonk.com/2010/05/wcf-improve-performance-with-greater-concurrency/
I'd like to know if it's possible to call a method on a WCF windows service while another one is executing ? I need this so I can call my Terminate method that sets a static variable shared by my threads that tells them to stop. But when I call the method on the service, it waits till the first one (Execute) is over before he takes the call...
You need to set the concurrency mode of the service behavior to ConcurrencyMode.Multiple like this:
[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple)]
class MyService : IMyContract
{
// ...
}
In this situation the framework will not try to synchronize access to the service instance allowing to execute multiple operations at the same time.