I have a console application, in which I have a connection to a third party windows service on a remote server by tcp/ip.
The call Hierarchy likes:
static class Program
{
[MTAThread]
static void Main()
{
MyApplication.Start();
The Start method
public static void Start()
{
lock (SyncVar)
{
ThreadStart ts = new ThreadStart(MainCode);
MainCodeThread = new Thread(ts);
MainCodeThread.IsBackground = false;
MainCodeThread.Start();
The detail of main thread has:
private static void MainCode()
{
try
{
// connect to the remote server, against a windows service
TelephonyServer tServer = new TelephonyServer(sIpaddress, "username", "password");
while (true)
{
Task consumer = Task.Run(() =>
{
if (data != "")
{
ProcessEachChannel(data);
});
Task producer = Task.Run(() =>
{
// blah blah
});
In the method ProcessEachChannel, we have
public bool ProcessEachChannel(string workItem)
{
ChannelResource cr = tServer.GetChannel();
// blah blah
}
Now the application is working well. However if I click the red exit cross of the application or click stop debugging button from Visual Studio, the resources ChannelResource cr is not destroyed at all. I found the fact from the remote server service control dashboard.
I tried some code
System.Diagnostics.Process process = System.Diagnostics.Process.GetCurrentProcess();
process.Exited += new EventHandler(OnExited);
It is not helpful. I heard some tricks to manage the thread by passing parameters to the main thread then set something true or false etc but just no clue.
The program will not exit until all running threads have been stopped.
Replace the while (true) in the thread code with while (!stopThread.WaitOne(10, false)) where stopThread is a WaitHandle like ManualResetEvent.
Then, when the application shuts down, Set the event and wait for the thread to exit.
Also note that some 3rd-party frameworks depend on Dispose being called on their object because they need to manage the lifetime of some separate threads they've spawned. F.e. read VoiceElements document and see how they call Disconnect and Dispose on a ChannelResource they've got from GetChannel(). Please check with the provider when and where you need to release used resources yourself.
If you kill the process, instead of closing it gracefully (and that is what you do when you close the console window or press the stop buttpn in debugger), there's no chance for any cleanup code to run.
you have to implement some exit handler, perhaps catching a ctrl-c press and then return from your threads, so all objects can cleanly dispose themselves.
Related
In the past, using Console apps, I've kept Akka.NET actor systems alive like this:
class Program {
static void Main(string[] args) {
using (var actorSystem = ActorSystem.Create("ExampleSystem")) {
var exampleActor = actorSystem.ActorOf(Props.Create(() => new ExampleActor()), name: "Example");
Console.WriteLine("Akka.NET ActorSystem is now running, press any key to shut down");
Console.ReadKey();
actorSystem.Shutdown();
actorSystem.AwaitTermination(timeout: TimeSpan.FromSeconds(5));
}
}
}
Without the Console.ReadKey(), what's the right way to manage the lifetime of an actor system for a WPF application?
(bonus points: I've heard that Shutdown and AwaitTermination are obsolete, but I'm not sure of the new best practice)
Currently, if you wish to shut down an ActorSystem you should use ActorSystem.Terminate(), which returns a Task that completes once the shutdown has finished.
There is also another property on the ActorSystem, WhenTerminated, which looks like it only exists so that you can get access to the termination task if you need it, without telling the system to terminate.
In your example, Console.ReadKey() is used to block and prevent the process from ending, which isn't necessary in a WPF app. You can either just let your wpf application close if you don't care about the state of the system, or terminate and wait for the termination task to complete if you need the system to shutdown cleanly.
I am working on a windows service written in C# (.NET 4.5, VS2012), which uses RabbitMQ (receiving messages by subscription). There is a class which derives from DefaultBasicConsumer, and in this class are two actual consumers (so two channels). Because there are two channels, two threads handle incoming messages (from two different queues/routing keys) and both call the same HandleBasicDeliver(...) function.
Now, when the windows service OnStop() is called (when someone is stopping the service), I want to let both those threads finish handling their messages (if they are currently processing a message), sending the ack to the server, and then stop the service (abort the threads and so on).
I have thought of multiple solutions, but none of them seem to be really good. Here's what I tried:
using one mutex; each thread tries to take it when entering HandleBasicDeliver, then releases it afterwards. When OnStop() is called, the main thread tries to grab the same mutex, effectively preventing the RabbitMQ threads to actually process any more messages. The disadvantage is, only one consumer thread can process a message at a time.
using two mutexes: each RabbitMQ thread has uses a different mutex, so they won't block each other in the HandleBasicDeliver() - I can differentiate which
thread is actually handling the current message based on the routing key. Something like:
HandleBasicDeliver(...)
{
if(routingKey == firstConsumerRoutingKey)
{
// Try to grab the mutex of the first consumer
}
else
{
// Try to grab the mutex of the second consumer
}
}
When OnStop() is called, the main thread will try to grab both mutexes; once both mutexes are "in the hands" of the main thread, it can proceed with stopping the service. The problem: if another consumer would be added to this class, I'd need to change a lot of code.
using a counter, or CountdownEvent. Counter starts off at 0, and each time HandleBasicDeliver() is entered, counter is safely incremented using the Interlocked class. After the message is processed, counter is decremented. When OnStop() is called, the main thread checks if the counter is 0. Should this condition be fulfilled, it will continue. However, after it checks if counter is 0, some RabbitMQ thread might begin to process a message.
When OnStop() is called, closing the connection to the RabbitMQ (to make sure no new messages will arrive), and then waiting a few seconds ( in case there are any messages being processed, to finish processing) before closing the application. The problem is, the exact number of seconds I should wait before shutting down the apllication is unknown, so this isn't an elegant or exact solution.
I realize the design does not conform to the Single Responsibility Principle, and that may contribute to the lack of solutions. However, could there be a good solution to this problem without having to redesign the project?
We do this in our application, The main idea is to use a CancellationTokenSource
On your windows service add this:
private static readonly CancellationTokenSource CancellationTokenSource = new CancellationTokenSource();
Then in your rabbit consumers do this:
1. change from using Dequeue to DequeueNoWait
2. have your rabbit consumer check the cancellation token
Here is our code:
public async Task StartConsuming(IMessageBusConsumer consumer, MessageBusConsumerName fullConsumerName, CancellationToken cancellationToken)
{
var queueName = GetQueueName(consumer.MessageBusConsumerEnum);
using (var model = _rabbitConnection.CreateModel())
{
// Configure the Quality of service for the model. Below is how what each setting means.
// BasicQos(0="Don't send me a new message until I’ve finished", _fetchSize = "Send me N messages at a time", false ="Apply to this Model only")
model.BasicQos(0, consumer.FetchCount.Value, false);
var queueingConsumer = new QueueingBasicConsumer(model);
model.BasicConsume(queueName, false, fullConsumerName, queueingConsumer);
var queueEmpty = new BasicDeliverEventArgs(); //This is what gets returned if nothing in the queue is found.
while (!cancellationToken.IsCancellationRequested)
{
var deliverEventArgs = queueingConsumer.Queue.DequeueNoWait(queueEmpty);
if (deliverEventArgs == queueEmpty)
{
// This 100ms wait allows the processor to go do other work.
// No sense in going back to an empty queue immediately.
// CancellationToken intentionally not used!
// ReSharper disable once MethodSupportsCancellation
await Task.Delay(100);
continue;
}
//DO YOUR WORK HERE!
}
}
Usually, how we ensure a windows service not stop before processing completes is to use some code like below. Hope that help.
protected override void OnStart(string[] args)
{
// start the worker thread
_workerThread = new Thread(WorkMethod)
{
// !!!set to foreground to block windows service be stopped
// until thread is exited when all pending tasks complete
IsBackground = false
};
_workerThread.Start();
}
protected override void OnStop()
{
// notify the worker thread to stop accepting new migration requests
// and exit when all tasks are completed
// some code to notify worker thread to stop accepting new tasks internally
// wait for worker thread to stop
_workerThread.Join();
}
I'm feeling so dumb to ask this but..
How can I prevent my app from exiting without blocking the thread?
Currently it is a console application. But it will be a "windows-app"
(right click in VS on the startup project -> app -> output type: (first) windows app - not a store app. This is just to have an "invisible" app without any kind of GUI. So I can't use Console.ReadLine() later)
What I'm currently doing
var app = WebApp.Start<OwinStartup>(url);
Console.ReadLine(); // wait until I press enter
app.Dispose();
I don't want to block my thread like this
while (isRunning)
{
Thread.Sleep(1000);
}
What possibilities do I have to achieve this?
So a disclaimer, I am not familiar with WebApp at all. However, you could use a ManualResetEvent to accomplish what you want.
using (var app = WebApp.Start<OwinStartup>(url))
{
ManualResetEvent stopHandle = new ManualResetEvent(false);//Might need to be true, I always get this mixed up.
//Pass handle to app somehow
stopHandle.WaitOne();
}
So this code creates the app and then creates a ManualResetEvent. This event is then passed to the app and then the thread stops and waits for it to be set. Inside the app you can set it whenever you want, you can read console input, wait for a button on a page to be clicked or whatever.
I am assuming here that the WebApp class handles creating another thread or uses async to handle web requests. Otherwise you would need to run the app on another thread.
If I have understood your question correctly you are looking for something like below.
Dispatcher.Run();
the above piece of code will keep the thread/app active and wait for message on the Dispatcher as long as shutdown has not been requested on that particular Dispatcher.
Not for a console project you need to add reference to WindowsBase
You can then decide to shutdown the application from another thread.
private static void Main(string[] args)
{
var waitThread = new Thread(Dispatcher.Run) {IsBackground = false};
waitThread.Start();
Console.WriteLine("Application is still running");
//to exit application shutdown waitThread here
}
https://msdn.microsoft.com/en-us/library/system.windows.threading.dispatcher.run(v=vs.110).aspx
A very simplistic approach will be to display a MessageBox with OK button only. This will block the execution until the user has clicked the button or simply pressed "Enter" key. This I think resembles the behavior of the "Console.ReadLine()" provided you don't actually expect any input at this stage.
You can do an asynchronous application wait using the async and await tag. And this is assuming you have .NET 4.5 as your framework.
private static bool hasExitedApp; // flag to be used for exiting
private static void Main(string[] args)
{
Console.WriteLine("Application is running...");
performAsynchronousWait();
Console.WriteLine("Application is still running...");
// do other processes here
}
private async static void performAsynchronousWait()
{
while (!hasExitedApp)
await Task.Delay(100); // Task.Delay uses a timer, so there's no blocking the UI
Console.WriteLine("Has excited the application...");
// do shutdown processes here
}
I used console here to show that the execution of main will still continue, but the method performAsynchronousWait is still executing. You're UI thread will continue but a background process will still happen.
I have a console app that runs some on demand reporting in a webapplication. The app starts, runs some housecleaning, starts a (1 second) timer, and blocks on a Console.ReadLine(); statement. (I've been meaning to stuff it into a service instead, but that's for another day)
Right now this has no exception-handling, so if the sql server it polls against goes down or there is a network hiccup, it just crashes. I'm trying to implement a crude exception-handling now. Inside the timer-callback I have stuffed the sql-query inside a trycatch. If it fails, it handles the exception by logging, increasing a failurecounter and resuming the timer. If it fails more than 5 times I want it to exit the app (sort of) gracefully. How can I force-quit a console app that is blocked with a readline statement?
Code in a gist: https://gist.github.com/cwattengard/11171563
I think a more elegant solution is to block with a reset event. The timer callback sets this at some point when it considers that it no longer has work to do.
static readonly ManualResetEvent reset = new ManualResetEvent(false);
static void Main(string[] args)
{
var t = new Timer(TimerCallback, null, -1, 1000);
t.Change(0, 1000);
reset.WaitOne(); // the application will sit here until the timer tells it to continue.
}
private static void TimerCallback(object state)
{
try
{
// do stuff.
}
catch (Exception e)
{
failureCounter++;
if (failureCounter > 5)
{
reset.Set(); // release the reset event and the application will exit,
return;
}
}
}
The best way would be to use some sort of signalling mechanism.
For example you start the main thread, do all your initialization (timer etc) then create a non signaled ManualResetEvent and wait on it to fire. If the callback from the timer decides the application should terminate it signals the ManualResetEvent and the main thread is released, completes, and terminates the program...
As a matter of general approach, you should always use signaling and ""cooperative multi-tasking"" within your application. In the sense you signal other threads\ tasks\ actors\ whatever to do stuff, you shouldn't forcefully kill them...
I actually develop a Windows service in VS 2012 / .NET 4.5.
The service is following the scheme of the code snippet below:
Using a timer
Executes some desired operation every couple of minutes.
The process takes about 10 minutes to complete
I use a single thread in the service
What I am worried about is that if somebody stops the service via the management console, it might be just during the process that the service is doing.
I have done some reading about stopping Windows service with request stop, but am a bit lost. Sometimes WorkerThreads are created, sometimes ManualResetEvents are created, but up to now I couldn't fully grasp the best way forward for my Windows service.
I need to wait until the processing is properly finished in the onStop method before stopping the Windows service.
What is the best way forward then, also considering the code snippet below?
Thanks all!
namespace ImportationCV
{
public partial class ImportationCV : ServiceBase
{
private System.Timers.Timer _oTimer;
public ImportationCV()
{
InitializeComponent();
if (!EventLog.SourceExists(DAL.Utilities.Constants.LOG_JOURNAL))
{
EventLog.CreateEventSource(DAL.Utilities.Constants.LOG_JOURNAL, DAL.Utilities.Constants.SOURCE_JOURNAL);
}
EventLog.Source = DAL.Utilities.Constants.SOURCE_JOURNAL;
EventLog.Log = DAL.Utilities.Constants.LOG_JOURNAL;
}
protected override void OnStart(string[] args)
{
int intDelai = Properties.Settings.Default.WatchDelay * 1000;
_oTimer = new System.Timers.Timer(intDelai);
_oTimer.Elapsed += new ElapsedEventHandler(this.Execute);
_oTimer.Start();
EventLog.WriteEntry(DAL.Utilities.Constants.LOG_JOURNAL, "Service " + DAL.Utilities.Constants.SERVICE_TITLE + " started at " + DateTime.Now.ToString("HH:mm:ss"), EventLogEntryType.Information);
}
protected override void OnStop()
{
if (_oTimer != null && _oTimer.Enabled)
{
_oTimer.Stop();
_oTimer.Dispose();
}
EventLog.WriteEntry(DAL.Utilities.Constants.LOG_JOURNAL, "Service " + DAL.Utilities.Constants.SERVICE_TITLE + " stopped at " + DateTime.Now.ToString("HH:mm:ss"), EventLogEntryType.Information);
}
private void Execute(object source, ElapsedEventArgs e)
{
_oTimer.Stop();
try
{
//Process
}
catch (Exception ex)
{
EventLog.WriteEntry(DAL.Utilities.Constants.LOG_JOURNAL, (ex.StackTrace + ("\r\n" + ex.Message)), EventLogEntryType.Error);
}
_oTimer.Start();
}
}
}
As a test case, I put a call to System.Threading.Thread.Sleep(500000) in the OnStop() callback of my Windows service. I started the service and then stopped it. I got the window with the progress bar indicating that the Service Control Manager (SCM) was attempting to stop the service. After about 2 minutes, I got this response from the SCM:
After I dismissed this window, the status of my service in the SCM changed to Stopping, and I noticed that the service continued to run in Task Manager. After the sleep elapsed (nearly 6 minutes later), the process stopped. Refreshing the SCM window showed the service was no longer running.
I take a couple of things away from this. First, OnStop() should really attempt to stop the service in a timely manner just as part of playing nice with the system. Second, depending on how your OnStop() method is structured, you could force the service to ignore a preemptive request to stop, instead stopping when you say so. This is not recommended, but it appears that you could do this.
As to your particular situation, the thing you have to understand is that the System.Timers.Timer.Elapsed event fires on a ThreadPool thread. By definition, this is a background thread, which means that it will not keep the application running. When the service is told to shut down, the system will stop all background threads and then exit the process. So your concern about keeping the processing going until it is finished despite being told by the SCM to shutdown cannot occur the way you've got things structured currently. To do that, you'd need to create a formal System.Threading.Thread object, set it as a foreground thread, and then use the timer to trigger this thread to execute (as opposed to being done in the Elapsed callback).
All of that said, I still think you'll want to play nicely with the system, which means timely shutdown of the service when requested to do so. What happens if, for example, you need to reboot the machine? I haven't tested it, but if you force your service to continue running until the processing is complete, the system may indeed wait until the process finishes before actually restarting. That's not what I would want from my service.
So I would suggest one of two things. The first option would be to break the processing into distinct chunks that can be done individually. As each chunk is finished, check to see if the service is stopping. If so, exit the thread gracefully. If this cannot be done, then I would introduce something akin to transactions to your processing. Let's say that you're needing to interact with a bunch of database tables and interrupting the flow once it's started becomes problematic because the database may be left in a bad state. If the database system allows transactions, this becomes relatively easy. If not, then do all the processing you can in memory and commit the changes at the last second. That way, you only block shutting down while the changes are being committed as opposed to blocking for the entire duration. And for what it's worth, I do prefer using ManualResetEvent for communicating shutdown commands to threads.
To avoid rambling any further, I'll cut it off here. HTH.
EDIT:
This is off the cuff, so I won't verify its accuracy. I'll fix any problem you (or others) may find.
Define two ManualResetEvent objects, one for shutdown notification and one for processing notification, and the Thread object. Change the OnStart() callback to this:
using System.Threading;
using Timer = System.Timers.Timer; // both Threading and Timers have a timer class
ManualResetEvent _shutdownEvent = new ManualResetEvent(false);
ManualResetEvent _processEvent = new ManualResetEvent(false);
Thread _thread;
Timer _oTimer;
protected override void OnStart(string[] args)
{
// Create the formal, foreground thread.
_thread = new Thread(Execute);
_thread.IsBackground = false; // set to foreground thread
_thread.Start();
// Start the timer. Notice the lambda expression for setting the
// process event when the timer elapses.
int intDelai = Properties.Settings.Default.WatchDelay * 1000;
_oTimer = new Timer(intDelai);
_oTimer.AutoReset = false;
_oTimer.Elapsed += (sender, e) => _processEvent.Set();
_oTimer.Start();
}
Change your Execute() callback to something like this:
private void Execute()
{
var handles = new WaitHandle[] { _shutdownEvent, _processEvent };
while (true)
{
switch (WaitHandle.WaitAny(handles))
{
case 0: // Shutdown Event
return; // end the thread
case 1: // Process Event
Process();
_processEvent.Reset(); // reset for next time
_oTimer.Start(); // trigger timer again
break;
}
}
}
Create the Process() method like this:
private void Process()
{
try
{
// Do your processing here. If this takes a long time, you might
// want to periodically check the shutdown event to see if you need
// exit early.
}
catch (Exception ex)
{
// Do your logging here...
// You *could * also shutdown the thread here, but this will not
// stop the service.
_shutdownEvent.Set();
}
}
Finally, in the OnStop() callback, trigger the thread to shutdown:
protected override void OnStop()
{
_oTimer.Stop(); // no harm in calling it
_oTimer.Dispose();
_shutdownEvent.Set(); // trigger the thread to stop
_thread.Join(); // wait for thread to stop
}
#Matt - thanks for the great code, really helpful.
I found it worked even better if I added another test on _shutdownEvent:
case 1: // Process Event
Process();
if(_shutdownEvent.WaitOne(0)) break; // don't loop again if a shutdown is needed
...