I have a WCF service setup to control a USB fingerprint reader from our .Net applications. This works fine and I can ask it to enroll users and so on.
The reader allows identification (it tells you that a particular user has presented their finger, as opposed to asking it to verify that a particular user's finger is present), but the device must be constantly polled while in identification mode for its status - when a user is detected the status changes.
What I want is for an interested application to notify the service that it wants to know when a user is identified, and provide a callback that gets triggered when this happens. The WCF service will return immediately and spawn a thread in the background to continuously poll the device. This polling could go on for hours at a time if no one tries to log in.
What's the best way to acheive this? My service contract is currently defined as follows:
[ServiceContract (CallbackContract=typeof(IBiometricCallback))]
public interface IBiometricWcfService
{
...
[OperationContract (IsOneWay = true)]
void BeginIdentification();
...
}
public interface IBiometricCallback
{
...
[OperationContract(IsOneWay = true)]
void IdentificationFinished(int aUserId, string aMessage, bool aSuccess);
...
}
In my BeginIdentification() method can I easily spawn a worker thread to poll the device, or is it easier to make the WCF service asynchronous?
I think it is much better to make the WCF service operation asynchronously. This MSDN article shows how to do it:http://msdn.microsoft.com/en-us/library/ms730059.aspx.
Related
I have a service that collects data and has to survive the app's life-cycle changes while app is in the background. This service resides in the same process as my app, i.e. registered in the manifest as well.
The service posts LiveData to the app, and the main app retrieves this LiveData by binding to the service and doing something like:
private void onServiceConnected(TicketValidatorService service) {
...
service.getStatus().observe(this, new Observer<SomeStatus>() {
#Override
public void onChanged(SomeStatus status) {
handleStatusChanged(status);
}
})
...
}
Is this considered bad practice? Or should I rather communicate via Messenger/Handler or LocalBroadcastManager stuff over the service/app boundary? It would be difficult to put the service in another process, but I don't think I have to do that for the sake of my task.
Communication to a local service directly is not considered to be a bad practice and in fact an official recommendation. There is no reason to complicate your code to support cross-process communication when you are not going to use it. Moreover this kind of communication involves marshaling / unmarshaling which adds restrictions on data types you can pass through and has some performance hit.
Also please note, starting from android 8 there are limitations on background services. So if you are not running your service as a foreground service it's not going to be alive for long time after your app goes to background.
We have a WCF service called service1 hosted in IIS.
We are creating another WCF service, say, service2, which will always be running in the background and will monitor if a file, say, X, is having enough data that has to be consumed by Service1.
If the file X is not having enough data then service2 will call another component which will load the data to the file.
So please suggest a hosting technique for service2 which fulfils all the above requirements and should be independent, i.e if the service2 is down, it should not impact service1 or vice versa. Both these services are a part of the same app-domain.
We have one scenario where we hosted the same as a window service. Now we are looking to try something else.
Please provide your valuable suggestions.
You're looking for the right kind of screwdriver to hammer a nail. 8-)
WCF services run on demand, based on network activity (a request comes in, the service runs and handles the request). However after a defined period with no activity the service shuts down and the resources are released, and the server waits for the next request, however the existence of a file containing the data you want does not create this type of request.
What you need is a Windows Service (the things that you see in the Services Control Panel). These run continuously and are appropriate for tasks that don't produce network requests, like monitoring to see if you have the data you need.
We have one scenario where we hosted the same as a window service. Now we are looking to try something else.
There really isn't anything else suitable for unattended operation. Windows Services are designed exactly for this type of task, while WCF Services aren't.
Apart from your hosting requirement you should also consider using a FileSystemWatcher if you haven't done so already. You would obviously have to add your own logic to meet your requirements.
Basic example:
protected override void OnStart(string[] args)
{
FileSystemWatcher Watcher = new FileSystemWatcher("some file path");
Watcher.EnableRaisingEvents = true;
Watcher.Changed += new FileSystemEventHandler(Watcher_Changed);
}
// This event is raised when a file is changed
private void Watcher_Changed(object sender, FileSystemEventArgs e)
{
// your code here
}
More complete example:
http://www.rhyous.com/2012/11/27/c-creating-a-service-to-monitor-a-directory/
I have a WCF which is configured on Windows Authentication. This means that only authenticated Windows users will be able to access. I have a method which does not return anything but spins up a thread that does some long running task under the called windows user impersonation.
My code is below:
public void SampleTask();
{
Task.Factory.StartNew(this.Activity);
}
private void Activity()
{
WindowsIdentity identity = ServiceSecurityContext.Current.WindowsIdentity;
using (WindowsImpersonationContext ctx = identity.Impersonate())
{
// Log status in a log database as "In Progress"
// Do long running task (accessing database as current user)
// retreive the results and save in a file
// Update the log database as "Complete"
}
}
My question is will the task still complete of retrieving the results and saving it and put the status as it should. Or will the impersonation will not work as there will be no open session. Or am I mistaken
Regards,
Girija Shankar
The session should remain open as long as the method is executing. Even if the method is returning void, the request that started the execution of the method will be replied to.
If you don't need a reply from the service, you can use the IsOneWay = true attribute on the method, which will tell the service to not send a reply to the client. Since this is a long-running method that is not returning data to the client, that makes it a good candidate for being a one-way method. In this case I'm not sure if the session would remain open or not, but it doesn't matter because the impersonation context will be scoped to the service, and have no dependency on the client.
In your method, you can see this because of the declaration:
WindowsIdentity identity = ServiceSecurityContext.Current.WindowsIdentity;
The variable identity is scoped to the Activity method.
using (WindowsImpersonationContect ctx = identity.Impersonate())
The variable ctx is likewise scoped to the using block within the Activity method.
The only time you would run into a problem that I can think of is if the service throws an exception and crashes - then of course the method wouldn't finish.
To sum up, since the impersonation is based on the identity the service is running under, and you're not returning any data to the client, session should have no impact on both the method running to completion or the identity the service is running under.
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.
From a little bit of reading around, it is my understanding that the only way to detect that a client has connected to my service is through writing my own code. I am using a Singleton service. I would like to display a message every time a client connects to my service that client x with ip xxx has connected. There is no built-in event that is generated? Am I correct?
No, I don't think there's any support in WCF for your requirement.
Not sure what you want to achieve with this, either. Your service class (in your case, just a single instance) really doesn't have any business putting up messages (on screen, I presume) - that really not it's job. The service class is used to handle a request and deliver a response - nothing more.
The ServiceHost class might be more of a candidate for this feature - but again, it's job really is to host the service, spin up the WCF runtime etc. - and it's really not a UI component, either.
What you could possibly do is this
have an Admin UI (a Winforms, console, or WPF app) running on your server alongside your service, providing an admin service to call
define a fast connection between the two services (using e.g. netNamedPipe binding which is perfect for intra-application messaging)
when your "real" service gets a call, the first thing it does is send out a message to the admin UI which can then pick up that message and handle it
That way, you could cleanly separate your real service and it's job (to provide that service) and the Admin UI stuff you want to do and build a cleanly separated system.
I have actually implemented my own connect, disconnect and ping service methods which I manually call from my client once the channel has been created. By using them as a kind of header section in all of my ServiceContract interface definitions (and their implementations, of course), they form an makeshift "base service definition" that only requires a bit of cut-n-paste.
The string-based parameters of connect and disconnect will be used to send client info to the server and return server info and (perhaps a unique connection id) to the client. In addition a set of timing reference points may make its way in also.
Note how SessionMode is required and the individual OperationContract properties IsInitiating and IsTerminating are explicitly specified for each method, the end result being what I would call a "single-session" service in that it defines connect and disconnect as the sole session bookends.
Note also that the ping command will be used as the target of a timer-based "heartbeat" call that tests the service connection state and defeats ALL connection timeouts without a single config file :-)
Note also that I haven't determined my fault-handling structure yet which may very well add a method or more and/or require other kinds of changes.
[ServiceContract( SessionMode = SessionMode.Required )]
public interface IRePropDalSvr {
[OperationContract( IsInitiating=true, IsTerminating=false )]
string connect (string pClientInfo);
[OperationContract( IsInitiating=false, IsTerminating=true, IsOneWay=true )]
void disconnect (string pClientInfo);
// ------------------------------------------------------------------------------------------
[OperationContract( IsInitiating=false, IsTerminating=false )]
string ping (string pInp);
// ------------------------------------------------------------------------------------------
// REST OF ServiceContract DEFINITION GOES HERE
One caveat: while I am currently using this code and its implemention in my service classes, I have not verified the code yet.