How do I start a service thread using the TPL? - c#

In the past, I've created the main thread of a service using the Thread object. Now I'm attempting to update it to the TPL. Unfortunately, the service ends after one pass in my loop. What do I need to do to keep the Task alive?
protected override void OnStart(string[] args)
{
_workerThread = Task.Run(() =>
{
while (true)
{
Console.WriteLine("go");
Thread.Sleep(10000);
}
});
}
More info:
In order to debug the service, I've set a flag to start the service as a console app if Environment.UserInteractive is set to true. So I guess I need it to keep going in console mode as well as a service.

When you create a new Thread, it is a foreground thread by default (its IsBackground is set to false). What that means is that your console application won't end until the thread does, even if Main returns before that.
Tasks, on the other hand, run on the thread pool, which contains only background threads. This means that when your Main returns, the application will exit, even if there is some Task still running.
You can fix this by Waiting on the Task at the end of your Main.

Related

How to keep a task running after the main thread ends?

I have an application that runs every 15 minutes. I need to add a new task (Maybe a Method) which will be called by the application and should run asynchronously, so the application can complete within the 15 Minutes. If the new task takes longer than the application is running, it will be aborted and can't complete its work. How can I keep a Task running?
There's a few ways you can go about this.
Independent process
The first is, don't run a task, run an independent process that can do the work. The first process will end when it needs to; the worker process will end when it needs to, and there's no communication between them (unless there needs to be for a different reason).
// in main thread...
var process = new Process(); // create the process
...
process.Start();
// process.WaitForExit(); this is commented out because you want main process to end without waiting
// main then ends here
Now the above means creating two separate executables; one for the launcher and one for the worker. That means two separate projects... or not.
What you can do is have both sets of functionality in the same executable, and invoke the functionality you need by separating it with command-line arguments. In your main you could do:
static void Main(string[] args)
{
if (args.Length == 1 && args[0] == "worker")
DoWorkerStuff();
else
{
var process = new Process(); // create the process
...
// use process API to call yourself with the arg
process.Start();
// process.WaitForExit(); this is commented out because you want main process to end without waiting
}
// main then ends here for both the launcher and the worker
}
I like this approach because you have full isolation due to process boundaries, and yet you don't have to compile and maintain separate projects.
Wait on the main thread
The second way is for the main thread to wait until the worker task is done. Trying to have tasks outlive the main thread can be problematic. Waiting is easy
// in main thread...
var task = ... // however you create the task
...
task.Wait(); // or one of the other Wait() overloads
There are, of course, other ways to start background work (e.g. using Thread) and for ways for the background work to signal the main thread, but these all require that original thread to wait until the work is done.

Task lifetime Child vs parent

I'm familiar with Task and Threads and I already know this.
Here is my code:
static void Main(string[] args)
{
var t = Task.Factory.StartNew(() => {
Thread.Sleep(3000);
Console.WriteLine("Child");
}, CancellationToken.None, TaskCreationOptions.AttachedToParent, TaskScheduler.Default);
Task.WaitAll(t);
Console.WriteLine("Parent");
}
Does Console.WriteLine("Child"); get called regardelss the call of Task.WaitAll(t); In other words: Is there a way to execute ALL started subtasks without waiting them (and not killed as soon as the parent finishes execution)?
A C# program will terminate as soon as there are no foreground threads running. Task.Factory.StartNew uses the thread pool thread to do its work, and thread pool threads are all background threads, not foreground threads, and as such don't prevent the entire program from terminating.
If you want to ensure that the entire program doesn't terminate you need to make sure you have at least one foreground thread running, this means either having the additional work you do in the Task you create do its work in a foreground thread, rather than a background thread (which is appropriate, if you want that work to prevent the application from terminating), or it will mean waiting in your one existing foreground thread for the others to finish.

Wait for RabbitMQ Threads to finish in Windows Service OnStop()

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();
}

How to replace ReadLine to exit my app?

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.

Watchdog for COM Thread

i am developing a WCF application that does not adhere to the idea world of a true SOA in that it will have a few basic calls.
1) Start Process
2) Check if process is still running
3) Get results
This is all fine, but in order for execution to return from the 'start process' I am running my code in a separate thread using
oThread = new Thread(new ThreadStart(wbrt.Calculate));
The problem is it has been known (though rare) for the COM call to hog and sit at 50~100% cpu and consume lots of memory. There is nothing I can do to prevent this.
What I want to do is have a watchdog thread that will kill off the COM call if it is still running after some time (say 5 minutes).
Is there a best practice here? I have been reading the following blog:
http://weblogs.asp.net/israelio/archive/2004/06/19/159985.aspx
in which he makes use of 'AutoResetEvent' and 'WaitOne' problem here is WaitOne is blocking so I'd have to have a thread within a thread.
Could I use a simple Thread Timer here? I saw that the timer will execute even if the thread has closed (i.e. finished ok) is that a problem if I use a flag or something to stop use of now dead objects?
Also I am creating my COM object using Activator.CreateInstance I tried Aborting the thread, but it does not kill the COM object and I have since read that Abort is bad.
My solution is to get the PID of the COM instance and simply kill, working on the assumption that if the timeout has hit diplomacy with the thread has gone out of the window.
Any thoughts well received!
Easiest way to do this is one ManualResetEvent with calling WaitAny() with a timeout value.
ManualResetEvent _evtActor = new ManualResetEvent();
public void Start()
{
this._evtActor.Reset();
ThreadPool.QueueUserWorkItem(new WaitCallback(DoStuff));
int result = ManualResetEvent.WaitAny(
new WaitHandle[] { this._evtActor },
30 * 1000); // Wait 30sec
if (result == ManualResetEvent.WaitTimeout)
{
Console.WriteLine("Timeout occurred!");
}
else
{
Console.WriteLine("Done!");
}
}
public void DoStuff()
{
Console.WriteLine("Doing stuff.");
Thread.Sleep(45 * 1000); // sleep for 45sec;
this._evtActor.Set();
}

Categories

Resources