I have a service that spins up a server which handles calls. The server can only start under certain conditions, and the service should try to start the server for a couple of minutes before giving up. Therefor, I use the service interface methods only to spin up a thread that handles the "try starting server and retry if it failed"-logic. But now I need to add termination of the service, if the server was not successfully started after, say, 5 minutes. The problem is, that I do not know how to marshal a call back to the service's "main" thread, since, as far as I understand, it is not an STA thread where I can just use a dispatcher. It is my understanding that I would have to do that in order to be able to System.Exit(1) my service. Any advice?
Points of clarification:
I do spin up a thread that is basically the service's main thread. Terminating that thread, however, does not couse the service to appear as stopped.
I'm giving you a tip and if you don't manage to implement it I will edit it later with more details. When you want to stop the service you should call the ServiceBase.Stop method.
Spin up a task to do the "try starting server and retry if it failed" and add a continuation (or pass Stop as Action argument) that will be executed when the task completes based on the result (or alternatively if you throw exception on failed to start, then verify Task.IsFaulted and call Stop() if true).
Related
I'm working in an environment with a light-weight web application (ASP.NET MVC 4.5), with pretty much all of the actual work being implemented in a separate web service application (ASP.NET Web API).
In nearly all cases, all the web site proper does is deliver pages that make AJAX calls to the web service site. But I have one use case in which a page needs to do an httppost to the main web site, and then have the controller action make a call against the webservice, and wait for a response.
Microsoft has, of course, a how-to page:
http://www.asp.net/web-api/overview/web-api-clients/calling-a-web-api-from-a-net-client
On that page, it says:
Many of the HttpClient methods are async, because they perform network I/O. In the RunAsync method, I'll show the correct way to invoke those methods asynchronously. It's OK to block the main thread in a console application, but in a GUI application, you should never block the UI thread.
So, the question, is blocking in a Controller Action, while we're waiting for a response from the webservice going to cause a problem? Yes, it means that the response to the browser is going to be delayed, but that seems inevitable given the circumstances.
My expectation would be that this wouldn't be an issue. Multiple requests are coming into the web service simultaneously, and that for this one request to block for a bit wouldn't have any unusual impact on overall performance. But I thought I'd ask.
When you await in your action, you're actually just returning the current thread back to the app's thread pool. So it really won't make much difference if you do your server side stuff synchronously or asynchronously unless you're getting enough requests to exhaust your thread pool.
Request comes in and is assigned a free thread from the thread pool (if no thread
is free then the request will sit and wait until one is free)
Web Api creates your controller and executes your action
When your action awaits, the thread is returned back to the thread pool
When the awaited task is done, a thread is assigned back to the request
The action finishes its work and returns or is awaited again which will return
the thread back to the thread pool again
With that in mind, it's obvious that you're not holding your api back by executing the action synchronously unless your thread pool is running out of available threads. In that case, the synchronous operation would hold you back because new requests are sitting and waiting to be assigned to a thread. But if it was async, that operation will return it's thread back to the thread pool so the new requests will be taken care of sooner.
Ok. I'm calling an external script [Edit: web service] that's doing an asynchronous task. It usually takes one to two minutes to complete.
In the meantime i want to display to the user the "please wait" message, since i need to make another call to check if the previous task has been completed yet before i continue.
Using timers is not exactly a good solution. I need the user to actually wait before i continue.
So the question i have is whether or not thread.sleep will put the entire web application to sleep or just the one for the current UI?
I don't want the UI for other website visitors to hang.
I'm not sure how this works in the production environment.
I use iis 7 on windows 2008 r2
Thanks
Thread.Sleep will only affect the current thread - but it's not what you want to do anyway.
You should return a complete response from your web application - but one which starts a Javascript timer to fire in a few seconds, and then make an AJAX call back to your web app to check whether the task has completed. (You should include some sort of "task ID" in your response so that the server knows which task to check.)
If you just sleep before returning the response, your user won't see any message until the sleeping has completed.
More info would be nice. However:
I guess you are going to make a website (asp.net mvc or webforms) since you are using iis7. Just run the server and let the client use a Ajax call to ask status of the task. The task when finished should be stored somewhere, preferably a database. You can also use xml or whatever to have a point where you can then save the taskid and or it is completed or not. And just let the ajax do a call every 5 sec until it returned at the taskid true on completed.
You shouldn't use Thread.Sleep. Assuming this is a web application...
One request should start the task and return a job token.
With another request, the user should be able to check the status of that job (by passing the token).
When the job is complete, the user should be able to get the result of the job (by passing the token).
I have a windows service that creates an instance of UdpClient class and listen for incoming request. I have a helper class to run it as a console application. When i run it as a console program, it runs fine and receive connections normally.
When deployed as a Windows Service using "installutil MyService" and start it, I get the following error:
"Error 1053: the service did not respond to the start or control request in a timely fashion."
The service don't even start, so I can't place a breakpoint in code.
Any suggestion about how to debug this or where to look?
Thanks.
Your Start() method is taking too long to do whatever it does when the service starts - if memory serves you have something like 15 seconds to kick-off whatever tasks the service is supposed to perform (on separate threads for long-running or continuous activities) and you must then allow the startup method to end so that the Service Controller recognises that the service has finished starting.
You didn't post any code, but my assumption would be that you're listening for UDP traffic synchronously - so the startup method just sits there waiting for UDP messages and never ends. Put the UDP listener into its own thread, start that thread, and then let the startup method end.
I am getting into windows services and looking over some tutorials, but they are all very dumbed down. They usually involve printing something out in the overridden OnStart method. That sounds like it gets called once. Now where would I put code that needs to be run continuously?
All of the On... methods in your service class should return as quickly as possible. They will end up being called whenever the Windows service controller interacts with your service, and the service controller will be waiting for a successful return. Whenever you use the Services Control Panel applet and you start or stop a service, that progress bar you see is what is shown while waiting for that service's equivalent of OnStart or OnStop to return.
So the typical thing to do in OnStart is one or more of the following:
start a separate thread that performs the constant task your service will perform
set up a timer (of the System.Threading.Timer variety) that will periodically perform whatever action your service does periodically (perhaps polling for some state)
start listening asynchronously on a network port, perhaps with a TcpListener or UdpClient
subscribe to some system event
In any of these cases, your service's task is performed asynchronously, and you exit from OnStart immediately. But remember to keep track of your thread, timer, TcpListener, or whatever, so that you can interact with it in OnStop (and optionally OnPause and OnContinue). Usually the thing to do is to dispose of any timers (so they won't fire any more), shut down any sockets or listeners, then set a ManualResetEvent. Any threads you have running should check this event periodically and exit once it's signaled. If you want to ensure a successful shutdown of the service and risk possible data loss, you might join to any running threads with a reasonable timeout (30 seconds is common), then abort any threads that are still running after the timeout has expired.
The same as any other project that has more than a couple of classes - you put it in a separate project.
The 'Windows Service' project should just contain the boilerplate stuff to start the service, any timers that are part of the service, and that sort of thing. Putting the rest in another project allows you to use your business logic in a desktop app, a web app, as a WCF service and so on later on.
To create any Windows Services the proper way, I stick to TopShelf library. It is IoC friendly and you can keep the Windows Service infrastructural code completly separate from the logic of the service. You also can run the service as a console application and just convert it to a windows service on production. I think it is "THE" way to create Windows Services and never looked back.
I have a webpage with a button that generates some files to a server path. (It takes somewhere from 5 to 20 minutes). I want to create an async task that will continue executing even after the user closes the browser. Is it possible to do this with asp.net 4 and C#?
You do not control the thread pool in an asp.net application. You cannot even guarantee that a request will be completed on the same thread that it started with. Creating threads uses the same application pool that the web server uses, and you can use up all the request threads leaving your web server unavailable to process requests.
You should implement a windows service that hosts a WCF service that you can call from within your web application. In the service you can then fire off a thread to process the long running process. At the end of that process you can then update a status flag (e.g from Processing to Complete) that the user can view to determine if the files are done processing.
I would recommend using Topshelf to implement your windows service, it will save you much headache.
Actually, it is recommended that you not do this. Instead, the recommended way is to create a service (e.g. a windows service) that performs your processing asynchronously. In your web application, you create methods that starts the process, and another method that polls the service to determine if processing has completed.
There are a number of reasons for this, but one of the biggest is that the default and recommended configuration for webservers allows the server to kill long-running requests.
Or that I didn't understand what you want to do, or that you don't need to do a thing.
After the request was sent, the request process continues no matter if the user browser was closed or not. You don't need to do a thing
Fabulous nature of stateless WEB applications...
Creating new thread / using thread pool is the easiest approach to create run away tasks.
Note that there is no guarantees that process will stay alive for duration of a long task - so be prepared to handle partial completion and manual restarts. I.e. AppPoll recycle due to config change.
Easiest way is to put your task on the ThreadPool. The thread pool threads will stay alive even after the web page has completed rendering. The code would look like the following:
/* Beginning Method */
object someData = new object();
ThreadPool.QueueUserWorkItem(new WaitCallback(ProcessAsync), someData);
/* Ending Method */
static void ProcessAsync(Object stateInfo)
{
string dataToString = stateInfo.ToString();
}
you have to create a thread that does the long running task
have a look at the below:
http://kiranpatils.wordpress.com/2010/01/01/performing-a-long-running-task-with-asp-net/
Anyway what ever you start on the server it will continue running even if the user close the browser(until you recycle the app-pool or restart the web server).