Progress notification in WCF for long running processes - How? - wcf

I have to design and implement a way to deal with long running processes in a client/server application. A typical long running process would/could take 2-3 minutes. I also need to report progress to the UI in the meantime and keep the UI responsive.
Having these in my mind I though of a few solutions:
One async request to start the process which starts the server-side process and returns an assigned LRPID (Long Running Process ID) then poll periodically from the client using that LRPID. (Pro: simple to deploy, no firewall messing around Con: Unelegant, resource consuming etc.)
Use a duplex binding (such as NetTcpBinding) and initiate callbacks from the server as progress is being made (Pro: Elegant, efficient, Con: Deployment nightmare)
[Your suggestion???]
What would be your take on this?

Here is a post by Dan Wahlin about how to create a WCF Progress Indicator for a Silverlight Application. This should be of some help.

If you do not want to have to worry about the client's firewall, etc... I would probably go with your first solution and use a BackGroundWorker to make the call in order to keep from blocking the UI thread. I did this recently for an app where a request to generate a report is put on a queue and is retrieved once it is done. It seems to work well.

Another way (without having to change the WCF binding) is to use a WebBrowser control in the WPF client, and SignalR to post progress messages from the server to that control.
Note that to avoid javascript errors that happen with the WebBrowser control (because by default it seems to use Internet Explorer version 7 which doesn't seem to be compatible with jQuery.js), you will need to add keys to the registry on the client machine to change the default for the client app to use IE10 or later - see http://weblog.west-wind.com/posts/2011/May/21/Web-Browser-Control-Specifying-the-IE-Version).
This could be a deployment nuisance (because admin rights seem to be needed - eg on a 64 bit Windows 8.1 pc - to add the registry keys).
Also, it still seems necessary to call the long running WCF method in a separate thread, otherwise the WebBrowser control doesn't seem to update its display to show the SignalR messages it is receiving. (This makes sense because the UI thread would otherwise have to wait until the WCF call had finished).
But I mention it as an alternative approach using a newer tool (SignalR) :)

Related

Starting a Saga with Bus.SendLocal(IMessage) instead of Bus.Publish(IEvent)

I'm working on an application that requires regular polling of a 3rd party API. We've used NServiceBus heavily throughout this project and I decided to use the benefits of a Saga to help maintain the state of my poller.
In short, the Saga is used to maintain information required to ensure the polling is done correctly, and also to give us the simplicity of creating a timeout (after each poll) in order to ensure the next poll takes place, even if the service is stopped/compromised/blocked for whatever reason.
My first issue arose when I decided to initiate the Saga by having the service subscribe to its own events, and then publish one of those events when the service started (using IWantToRunWhenBusStartsAndStops). The problem with that was that the service would start and therefore publish the event, but it would happen before the subscriptions were created. The service would therefore not handle the event that was meant to kick off the whole Saga, unless I restarted it. Restarting the service in order to bypass this problem is not a solution that I want to even consider.
Since then, and with some playing around, I have discovered that using
Bus.SendLocal(new MyMessage()); (MyMessage implements IMessage)
will effectively start the Saga, without the need for subscription. The Saga is created in the database (I use NHibernate & MSSQL for persistence), and the timeouts are correctly created and function exactly as expected.
My only problem with this solution is that I am doing something that I cannot find any reference to in the NServiceBus documentation, and I'm concerned that I may be utilising a "feature" that may disappear in a future version, due to actually being an unintended side-effect.
In a nutshell - I'm starting a Saga by sending an IMessage using SendLocal. It works 100% and fixes all my issues, but is it "correct"?
Your solution is absolutely correct and there is no reason I can think of not to do that.

calling a long running vb6 com object in classic asp .. time out error

I have a long running vb6 Com object called from a classic asp page
it works perfectly when there is not a lot to do but it times out if it has to do a lot.
is there a way of calling it async so it wont time out or
could i call a progress bar to keep on refreshing the client so it wouldnt time out ?
Set objQReport = Server.CreateObject("ReportGenerator")
mainRpt = objQReport.GenerateReport(MySessionRef) ' times out here sometimes
Set objQReport = nothing
any tips would be helpful
Web technology is not really suited for long-running tasks, but you have several options:
One option is to do an AJAX-call to a second ASP page. As soon as you're ASP is running, the server will finish the process, even if the client (the browser/AJAX that did the actual call) is no longer connected.
This method does use web-technology to process a long running task and the downside is that you are burdening your IIS machine with performing this long-running-task, leaving less performance for the thing IIS is good at; serving webpages.
So in your landing page (say default.asp) do an AJAX call to your (long-running) report page. How to do an ajax call depends on what (if any) javascript library you use. in Jquery it would be something like this:
<script type="text/javascript">
/* AJAX call to start the report generation */
$(document).ready(function(){
$.get("[URL_OF_YOUR_LONG_RUNNING_PROCESS]", function(data)
{
alert(data);
});
});
</script>
As you can see I am alerting any data that is returned from this URL, but in your case that is probably not what you want. You want your visitor to keep browsing while the long running process keeps working.
This way, the URL is called asynchronously. The server will start processing the URL and the browser doesn't have to wait for it. The server will continue and finish the long running task in the background.
Please note that you will still have to increase the server.scripttimeout on your asp page that runs the long process. This just makes sure that the user can continue browsing, the server will still respect the server.scripttimeout setting that is configured, and fail if it takes too long.
A widely used second option is to use a message queue. A message queue accepts messages and guarantees delivery of these messages, even if the computer or network goes down.
Microsoft Windows has MSMQ built in (you'll have to enable it in the software settings), and you can use this from classic ASP. The queue will store messages and deliver them to a consumer. The consumer is something you need to write yourself; an application that can read a queue and process the messages inside.
What you do is have ASP write a message to the MSMQ, containing information on what task to perform and its parameters.
Your consumer application will have to poll the MSMQ, read the message and start the long-running process. This will then run completely independent of IIS, and can even be run on a totally different computer (MSMQ can run across networks).
The downside of this second method is that you will have to write a consumer, most likely in a bit more low level language like VB or C# (though you might be able to use Python for example), and preferably write it as a service. I don't know how comfortable you are in (one of) these languages, but if you wrote the COM object yourself, it would be trivial to write an executable in VB6 that polls an MSMQ and calls the COM object.
Below are some links to get you started.
http://support.microsoft.com/kb/173339
http://technosock.blogspot.nl/2007/07/microsoft-message-queue-from-classical.html
http://www.informit.com/articles/article.aspx?p=131272&seqNum=6
Hope this helps,
Erik

Is it possible to do long polling with WCP on Windows Phone 7?

I want to push data to from a server to Windows Phone 7 client in an intranet environment.
I certainly don't want to use Microsoft Push Notification Service for this.
Is it possible to use WCF and long polling
I wrote this article on long polling - perhaps it would help?
http://xyzzer.wordpress.com/2011/03/10/real-time-client-server-communication-on-windows-phone-with-long-polling/
Long polling is just asynchronous programming with a, potentially, very long time out before the callback is called.
There is nothing in WCF (assuming that's what you meant in the title) or Windows Phone 7 that prevent this from being used. There is, however, a big consideration specific to using this technique on Windows Phone 7 though.
The issue you'll have with this on WP7 is that the app you create cannot run in the background and so must be constantly running from the time that the request was sent to the time that the response is received. Depending on how long your polling will be this may or may not be an issue.
As a partial solution you could consider disabling idle detection as this would keep the app running until the user stopped it (or triggered tombstoning).
Push Notifications are THE solution to sending a message (or a response) to a phone when the application isn't running.
Hopefully this will change in the future but that's how it is for now.

Best way to keep a .net client app updated with status of another application

I have a Windows service that's running all the time, and takes some action every 15 minutes. I also have a client WinForms app that displays some information about what the service is doing. I'd like the forms application to keep itself updated with a recent status, but I'm not sure if polling every second is a good move performance-wise.
When it starts, my Windows Service opens a WCF named pipe to receive queries (from my client form)
Every second, a timer on the winform sends a query to the pipe, and then displays the results. If the pipe isn't there, the form displays that the service isn't running.
Is that the best way to do this? If my service opens the pipe when it starts, will it always stay open (until I close it or my service stops)? In addition to polling the service, maybe there's some way for the service to notify any watching applications of certain events, like starting and stopping processing? That way, I could poll less, since I'd presumably know about big events already, and would only be polling for progress.
Anything that I'm missing?
I would steer clear of polling if possible. You're much better off adopting an event-based mechanism, which reduces overhead and provides just-in-time status updates as necessary.
You're already ahead of the curve. WCF is definitely the way to go here for .NET-based applications. And since your form and service are on the same system, the named pipe binding is the one to use as well. Now all you need is to have your service publish events, including periodic status updates, that your form can listen to when it's open.
The easiest way I've found to do this is to use Juval Lowy's Publish-Subscribe Framework. The neat thing about this framework is that it decouples the publisher from the subscriber. The publisher publishes events, not caring if a subscriber is there or not. If a subscriber is present, the event is forwarded for its consumption. Based on your description, I think this would work very well for you.

Compact Framework - System.Threading.Timer stops when the user turns off the screen

I have an application that needs to "poll" a webservice to see if the user has any new messages waiting. I have no control over the webservice so I cannot switch to a "push" mechanism, I'm stuck making a request every X number of seconds to see what's available.
I am using a System.Threading.Timer to make the request every so often, but am encountering a few problems. The biggest is that it stops running when the phone is sent into "standby" mode (screen off, but still able to get calls and email/txt notifications).
I'd really like it to behave like other background applications. What can I do to make it work without being too big of a drain on the battery?
Hate to answer my own question, but I was pointed to this, which was able to perform even when the device is asleep. Looks like it's working perfectly.
There's nothing you can do, AFAIK. Standby mode is meant to suspend the processor to save power, and there's no way your code can execute if the processor isn't running. There are things your application can do to prevent the device from going into standby mode, but this really isn't advisable at all.
Yep. Similar to how MusiGenesis has answered, you won't be able to do much without keeping the device up and running. Similar to how some phones will notify that "Game/App Running" and thus your battery is being slapped around.
What about writing an interface from your phone to leverage text messaging (which still works) and get it to send a text message to the web service? Would that be possible? I'm guessing that sort of method might also stop running, but I figure it's a thought?
I'm not sure about compact framework, but in Win32 there is WaitableTimer that can wake up computer from standby. It takes some native calls though as there's no wrapper in .Net.
Although you can't modify the webservice, you might be able to add a second "shadow" webservice in between your clients and the original webservice. The shadow webservice could poll the original webservice and then "push" anything it finds out to the PDAs.
I think you might still have the same problem, though. I've never done "push" from a webservice, but I think it's basically implemented by having the client make an initial call to a webservice method that takes a delegate to a method in the client, which the webservice then hangs onto. When the webservice needs to push something, it calls that delegate. If the client has gone into standby mode in the meantime, the attempt to call the delegate from the server will fail.