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.
Related
I have a WCF service and I have the following (simplified) class:
public class PerOperationSingleton : IDisposable
{
private static bool _hasInstance = false;
public PerOperationSingleton()
{
if(_hasInstance)
throw new InvalidOperationException("Cannot have multiple instances during a single WCF operation");
_hasInstance = true;
}
public void Dispose()
{
_hasInstance = false;
}
}
I guess, it's pretty self explanatory piece of code. I don't need a singleton for entire WCF service but only during a single operation call. If one instance of the PerOperationSingleton is disposed, it should be safe to create a new instance during the same WCF operation.
The problem is that I don't know how to make the _hasInstance variable to be effective only for one WCF operation. I know about [ThreadStatic], but I've heard that ASP.NET and WCF do not guarantee that an operation will be executed on a single thread - it might be transferred to another thread.
I definitely don't want my _hasInstance = true to move to thread pool and get incorrectly detected if some other operation picks that thread from the pool.
If WCF operation moves to another thread, I would like the _hasInstance variable to keep the "true" value if it was set.
And I don't want to change some global settings for my WCF service to avoid affecting the performance or get into some problems which will be hard to debug and solve later (I don't feel proficient enough in advanced ASP.NET and WCF topics).
I cannot store _hasInstance in session either because my client requested to disable .NET sessions for various reasons.
I would like the class PerOperationSingleton actually to be environment agnostic. It shouldn't really know anything about WCF or ASP.NET.
How do I make _hasInstance variable static during entire call of my WCF operation and don't affect other WCF operations?
I would consider using OperationContext to make you data "static" during the operation call.
Here is a similar discussion Where to store data for current WCF call? Is ThreadStatic safe?
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.
I have a long running operation:
void LongRunningOperation(string someValue);
How do i call it asynchronously (I want a fire and forget mechanism)?
you can set the mode to oneway.
you do not require to call these methods asynchronously. call to the methods returns as soon as they are call if the mode is one way.
use:
[OperationContract(IsOneWay = true)] attribute to describe your operation contract.
Assuming that you have already configured your proxy to the service, you will need to do the following (in VS):
Open your project that references the service, then go to service references.
Right-click the relevant service reference and select 'Configure Service Reference' from the context menu.
Tick the box that says 'Generate asynchronous operations'
After your client code regenerates, you will see a method that says BeginLongRunningOperation; that's your async method.
I have below requirements:
(1) Perform 'action A' when user requests for it.
(2) We also want to perform the same 'Action A' twice in a day even if users don't request for it.
I have a WCF web service which has method XYZ that performs action A. The method XYZ will be called when user requests for it.
Now question is, can I schedule this action without creating window service (which can host this service) or creating proxy?
Is there a way to perform an action by user request and schedule that same action, using only one application?
No, WCF cannot be auto-scheduled. You need to implement a Scheduled Task (see Scheduling jobs on windows), a Windows Service with a timer (which you've said you don't want to do, if I understand correctly) or some other application with a timer.
You could start a thread as per the other answer but this relies on your service calling itself - I'd prefer to call it externally, from another process.
A scheduled task can run an executable. You could write a console application that calls your WCF service, logs any result (if necessary) and then completes.
I normally prefer to implement this type of timer through a Windows Service, simply because the Windows Service can be monitored, can log, and can auto-start / auto-restart - install it and it 'just works'. If I didn't want to use a Windows Service then I'd schedule a task.
I typically do this by just calling the WCF service method from some kind of task scheduler. In a really simple form, you could just spawn a Thread from your service, that runs the WCF method periodically. Again this isnt the best solution, but its easiest to demonstrate. You could use some other scheduler library to do this too...
[ServiceContract]
public class SomeClass
{
[ServiceOperation]
public void SomeServiceMethod() { ... }
Then somewhere in the application startup:
Thread t = new Thread(new ThreadStart(CallService));
t.Start();
...
// this will call the WCF service method once every hour
public void CallService()
{
Thread.Sleep(3600000); // sleep 1 hour
new SomeClass().SomeServiceMethod();
}
This is one way to do it, although not the best way, but basically you can just call the WCF service method just like any other method in the application.
We are developing a WCF based system. In the process we are trying to lock some data from being modified by more than one users. So we decided to have a data structure that will contain the necessary information for the locking logic to execute (by for example storing the ID of the locked objects)
The problem we are having is persisting that data between sessions. Is there anyway we can avoid executing expensive database calls?
I am not sure how can we do that in WCF since it can only persist data (in memory) during an open session.
Static members of the service implementing class are shared between sessions & calls.
One option would be to use static members as Jimmy McNulty said. I have a WCF service that opens network connections based on a user-specified IP address. My service is configured for PerCall service instance mode. In each session, I check a static data structure to see if a network connection is already opened for the specified IP address. Here's an example.
[ServiceContract]
public interface IMyService
{
[OperationContract]
void Start(IPAddress address);
}
[ServiceBehavior(InstanceContextMode=InstanceContextMode.PerCall)]
public class MyService : IMyService
{
private static readonly List<IPAddress> _addresses = new List<IPAddress>();
public void Start(IPAddress address)
{
lock(((ICollection)_addresses).SyncRoot)
{
if (!_addresses.Contains(address)
{
// Open the connection here and then store the address.
_addresses.Add(address);
}
}
}
}
As configured, each call to Start() happens within its own service instance, and each instance has access to the static collection. Since each service instance operates within a separate thread, access to the collection must be synchonized.
As with all synchronization done in multithreaded programming, be sure to minimize the amount of time spent in the lock. In the example shown, once the first caller grabs the lock, all other callers must wait until the lock is released. This works in my situation, but may not work in yours.
Another option would be to use the Single service instance mode as opposed to the PerCall service instance mode.
[ServiceBehavior(InstanceContextMode=InstanceContextMode.Single)]
public class MyService : IMyService
{ ... }
From everything I've read, though, the PerCall seems more flexible.
You can follow this link for differences between the two.
And don't forget that the class that implements your service is just that - a class. It works like all C# classes do. You can add a static constructor, properties, event handlers, implement additional interfaces, etc.
Perhaps a caching framework like velocity help you out.
Create a second class and set its InstanceContextMode to single and move all the expensive methods there, then in your original class use that methods.