I used this example to implement WCF service that fires events (using callback) to all clients when something happening on the service. The problem is that this example works only when the service instance is percall.
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall, ConcurrencyMode = ConcurrencyMode.Reentrant)]
I want to use single instance but it won't work.It fires all the events to the last subscribed client.
Please help.
The sample has InstanceContextMode.PerSession, not InstanceContextMode.PerCall. Each subscribed client is associated with a separate instance of MyService. Each of these instances has a member field _callbackInstance which holds the reference to its particular client's callback channel. All the instances of MyService are associated into a "chat room" via the static event Broadcast, and when a particular client says something, the code iterates through the invocation list of the static event to broadcast to each subscribed client.
If you make MyService a singleton, _callbackInstance only contains the last subscribed client's callback channel, which is why you see the behaviour you describe.
In order to make the service class operate correctly as a singleton instance, you would have to replace _callbackInstance with a collection containing all the callback channels for the subscribed clients, and manage the additions and deletions from this collection yourself as clients arrived and left. Broadcasting would then involve iterating this collection. The drawback of this approach is that multiple clients may be calling the service concurrently, and you therefore need explicitly to synchronise access to the members of the class in order to ensure thread-safety and correct behaviour.
Thanks to Chris, I found this example showing how to handle multiply callback subscribers when using InstanceContextMode.Single. The example showing how to manage a dictionary (list is also possible) of callback channels.
Igal.
Related
I've been trying for a few days, and struggling with a best practice for this - any ideas?
Contrived private message example:
Multiple users logged into blazor server
Server subscribes to an event bus/message queue to receive NewMessageEvent
Only the user that is the intended recipient should be updated.
I can create a singleton to subscribe to the message queue.
I can then use a singleton that I inject to the required blazor component to add the message to a list and issue a stateHasChanged event.
That would update all connected clients (not ideal, the service injected to the components should be scoped).
Options so far:
I could verify the recipient for the message inside the blazor component, but it sort of feels the wrong place
Subscribe to the queue once per circuit (The queue still holds all messages though)
What I was hoping to do, was possibly create a service locator based on the circuit Id and connected userId using a circuit handler, and call a function like: NewMessageReceivedFor(userId), if that finds a matched circuit, then call the scoped service function.
This means that I should call a scoped service from a singleton (not allowed by DI through the constructor), by some form of GetRequiredService, but can I get that scoped service by specifying a circuit Id?
I currently feel Im either 90% there, or in the wrong forest, let alone up the wrong tree.
You could have a Singleton service for dealing with all messages, and then a Scoped service that subscribes to an event on the Singleton and then only triggers its own event if the message is for the current user (you'd need a service registered as Scoped to get the current user ID).
That way each user will only get a notification when the message is meant for them.
Don't forget to implement IDisposable on the Scoped service, so you can unsubscribe from the Singleton service.
I have a notification service that handles events and publishes them to clients using various technologies, such as SignalR. I want every instance of my notification service to pick up and handle these events. However, NServiceBus only allows any one instance of my notification service endpoint to pick up the event, and the other instances never get it.
My current workaround for this is to create a separate named endpoint for each instance of my notification service (the name has the server host name added to it), but then I have to make sure I unsubscribe from the event when the instance goes down or is moved to another server.
Is there a better way to do this? It would be nice if I could configure NServiceBus to create a separate incoming queue for each endpoint instance in this case, but I can't figure out how to do that, or even if NServiceBus supports such a use case.
You are correct. NServiceBus does not support such a case. Subscribers are always treated as logical endpoints, so individualized queues would not be used even if they were available.
Differentiating the instances by modifying the endpoint name is the most straightforward way to achieve what you want.
Changing your differentiator to a controllable runtime value, for instance an environment variable, would at least alleviate the need to unsubscribe when an instance is moved.
Also, if you want to review the scenario in more detail please don't hesitate to reach out to us directly, we might have other approaches to suggest. Just open a support ticket.
How can I make the WCF server instance (the instance of the class in the .svc.cs / .svc.vb file) stay alive between requests?
It's a stateless, read-only type of service: I'm fine with different clients reusing the same instance. However, it's not thread-safe: I don't want two threads to execute a method on this instance concurrently.
Ideally, what I'm looking for is that WCF manages a "worker pool" of these instances. Say, 10. New request comes in: fetch an instance, handle the request. Request over, go back to the pool. Already 10 concurrent requests running? Pause the 11th until a new worker is free.
What I /don't/ want is per-client sessions. Startup for these instances is expensive, I don't want to do that every time a new client connects.
Another thing I don't want: dealing with this client-side. This is not the responsibility of the client, which should know nothing about the implementation of the server. And I can't always control that.
I'm getting a bit lost in unfamiliar terminology from the MSDN docs. I have a lot working, but this pool system I just can't seem to get right.
Do I have to create a static pool and manage it myself?
Thanks
PS: A source of confusion for me is that almost anything in this regard points toward the configuration of the bindings. Like basicHttp or wsHttp. But that doesn't sound right: this should be on a higher level, unrelated to the binding: this is about the worker managers. Or not?
In the event that you have a WCF service that centralizes business logic, provides/controls access to another “single” backend resource (e.g. data file, network socket) or otherwise contains some type of shared resource, then you most likely need to implement a singleton.
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
In general, use a singleton object if it maps well to a natural singleton in the application domain. A singleton implies the singleton has some valuable state that you want to share across multiple clients. The problem is that when multiple clients connect to the singleton, they may all do so concurrently on multiple worker threads. The singleton must synchronize access to its state to avoid state corruption. This in turn means that only one client at a time can access the singleton. This may degrade responsiveness and availability to the point that the singleton is unusable as the system grows.
The singleton service is the ultimate shareable service, which has both pros(as indicated above) and cons (as implied in your question, you have to manage thread safety). When a service is configured as a singleton, all clients get connected to the same single well-known instance independently of each other, regardless of which endpoint of the service they connect to. The singleton service lives forever, and is only disposed of once the host shuts down. The singleton is created exactly once when the host is created.
https://msdn.microsoft.com/en-us/magazine/cc163590.aspx
Presently I have one class which monitor serial ports for incoming data, process the data and raises events through delegates/events based on the received data. This is a stand alone application. Now I have to convert it to a service so that the serial port monitor class will start as a service when the windows starts and a client applications subscribes to the events from either a remote PC or from the local machine. I have seen many articles on using WCF for this kind of applications. But WCF is message based and it will create a service obect when the client is requested. But my requirement is the service should be started automatically and the client application should be able to subscribe for the events of the service class instance which is already created during startup. How can I achieve this using WCF ?
The default behavior in WCF is to create a new instance of your service class to handle each incoming request, but you can override this by decorating your class with:
[ServiceBehavior(InstanceContextMode=InstanceContextMode.Single)]
To get good performance with a Singleton, though, there's a few things you'll need to consider:
Since you'll likely need to do some configuration of your Singleton instance, you'll probably want to use the ServiceHost constructor method that takes a Singleton instance as an argument. (For an example, see Figure 8 Initializing and Hosting a Singleton in this article
Threading: The default threading model (ConcurrencyMode) only allows a single thread to have access to your Singleton instance at a time. You may need to look at using ConcurrencyMode = ConcurrencyMode.Multiple to get good performance (which means you'll need to handle threading-related issues yourself).
Make sure the methods in your Callback contract are marked as [OperationContract(IsOneWay = true)] so that publishing events back to the subscribers doesn't cause your service instance to block until the event handler completes. (Using WCF in this way is covered in detail in this article by Juval Lowy
I am trying to understand how instances with WCF works. I have a WCF service which the InstanceContextMode set to PerCall (so for each call of every client a new instance will be created) and ConcurrencyMode set to Single (so the service instance is executing exactly one or no operation call at a time).
So with this I understand that when a client connects a new instance is created. But what happens when the client leaves the service. Does the instance die. The reason I ask is because I need to implement a ConcurrentQueue in the service. So a client will connect to the service and put loads of data to be processed and then leave the service. The workers will work of the queue. After the work is finished I need the instance to be destroyed.
Basically, learning from the "WCF Master Class" tought by Juval Lowy, per-call activation is the preferred choice for services that need to scale, i.e. that need to handle lots of concurrent requests.
Why?
With the per-call, each incoming request (up to a configurable limit) gets its own, fresh, isolated instance of the service class to handle the request. Instantiating a service class (a plain old .NET class) is not a big overhead - and the WCF runtime can easily manage 10, 20, 50 concurrently running service instances (if your server hardware can handle it). Since each request gets its own service instance, that instance just handles one thread at a time - and it's totally easy to program and maintain, no fussy locks and stuff needed to make it thread-safe.
Using a singleton service (InstanceContextMode=Single) is either a terrible bottleneck (if you have ConcurrencyMode=Single - then each request is serialized, handled one after another), or if you want decent performance, you need ConcurrencyMode=Multiple, but that means you have one instance of your service class handling multiple concurrent threads - and in that case, you as a programmer of that service class must make 100% sure that all your code, all your access to variables etc. is 100% thread-safe - and that's quite a task indeed! Only very few programmers really master this black art.
In my opinion, the overhead of creating service class instances in the per-call scenario is nothing compared to the requirements of creating a fully thread-safe implementation for a multi-threaded singleton WCF service class.
So in your concrete example with a central queue, I would:
create a simple WCF per-call service that gets called from your clients, and that only puts the message into the queue (in an appropriate fashion, e.g. possibly transforming the incoming data or something). This is a quick task, no big deal, no heavy processing of any kind - and thus your service class will be very easy, very straightforward, no big overhead to create those class instances at all
create a worker service (a Windows NT service or something) that then reads the queue and does the processing - this is basically totally independent of any WCF code - this is just doing dequeuing and processing
So what I'm saying is : try to separate the service call (that delivers the data) from having to build up a queue and do large and processing-intensive computation - split up the responsibilities: the WCF service should only receive the data and put it into a queue or database and then be done with it - and a second, separate process should do the processing/heavy-lifting. That keeps your WCF service lean'n'mean
Yes, per call means, you will have a new insance of the service per each connection, once you setup the instance context mode to percall and ConcurrencyMode to single, it will be single threaded per call. when the client leaves, done with the job, your instance will dispose. In this case, you want to becareful not to create your concurrentqueue multiple times, as far as i can imagine, you will need a single concurrentqueue? is that correct?
I would recommend you to use IntanceContextMode=Single and ConcurrencyMode to Mutli threaded. This scales better.if you use this scheme, you will have a single concurrent queue, and you can store all your items within that queue.
One small note, ConcurrentQueue, has a bug, you should be aware of, check the bug database.