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

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.

Related

How do I start a service thread using the TPL?

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.

Stop execution of any method without closing the application

I have an application which runs on a single thread, but does a lot of things (executing methods in a loop to automate webbrowser app).
I am a beginner, so the code is probably poorly organized, but I need to add a following feature to the program - a STOP button.
What it needs to do is simply send a 'return;' to any method that is or would be executed next, so that the program returns to a ready-and-waiting stage (i.e. I don't loose user provided data, but no other iteration of any loop is carried out etc.).
Any idea?
I tried System.Threading.Thread.CurrentThread.Abort(); but this actually kills the whole application. Any idea for a good generic solution?
Cheers!
Well first of all if you are just using one thread with your application. Then you cant send cancelTokens to your methods. However if you start using Tasks, which are threads then you can provide yourself the ability to use cancelTokens on your methods.
Here is a very simple example I wrote of using a cancelToken in a program that has threads.
class Program
{
static void Main(string[] args)
{
bool cancelToken = false;
Thread t = new Thread(new ThreadStart(() =>
{
while (!cancelToken)
{
Console.WriteLine("Running....");
Thread.Sleep(1000);
}
}));
t.Start();
Console.ReadKey();
cancelToken = true;
t.Join();
}
}
If you have a single-threaded GUI program, then you can't take any user commands while it's processing something. If you do as others have suggested, and dump the processing into a worker thread, then you can send an interrupt signal to that thread to stop it.

Start a process after a certain time interval in C#?

I have a c# wpf application where in the main() method, I check for a certain condition and if it is true, I run a different process, however, I need to start the process after a certain timeout. So, for eg:
override OnStartUp()
{
if(condition == true)
{
ProcessStartInfo p = new ProcessStartInfo("filePath");
p.Start(); // This should wait for like say 5 seconds and then start.
return; // This will exit the current program.
}
}
I could use Thread.Sleep() but that will cause the current program to sleep as well.
So, in other words, I want the current program to terminate immediately and then new process to start after 5 seconds.
Thanks!
Is this possible?
What if the first process creates a third program. The first program exits immediately, whilst the third one will simply sleep for 5 seconds and then will start your second program.
You've got a few options:
Modify the process being launched and put the delay there. You can even wait for "the parent has ended" instead of a fixed time.
Windows built-in Scheduled Tasks
A batch file that uses the sleep command and then runs the program
You can use Task Scheduler api and setup one time task that will start app after next 5 seconds.Nice managed wrraper: taskscheduler.codeplex.com
You need to create a new Thread. In this thread you can use Thread.Sleep without blocking your program.
public class MyThread
{
public static void DoIt()
{
Thread.Sleep(100);
// DO what you need here
}
}
override OnStartUp()
{
if(condition == true)
{
ThreadStart myThread = new MyThread(wt.DoIt);
Thread myThread = new Thread(myThread);
myThread.Start();
}
}
I can recomend the very powerful
http://quartznet.sourceforge.net/
For all your scheduling needs.

C# Run multiple non-blocking external programs in parallel

I need to run several instances of an external executable from my app. The average run time for this executable is about 3 minutes.
I want to redirect output from these processes, and update a progress bar in my GUI.
Of course I don't want to wait for them to return before I can continue using my app.
I think I should create a thread for every instance, and update my progress bar when a thread finishes.
Is this the right approach ?
Also, do you recommend a good resource / documentation to understand how it works ? I've found http://www.dotnetperls.com/threadpool only.
edit : these processes are network-based, ie: the run time may vary a lot depending on the link latency/bandwidth.
Concerning the progress bar, I would like to update it every time a process finishes. Is there a handler for that ? Later i will add more detailed update, based on the processes output to increase the progress done at each execution step.
edit 2 :
Thanks for your inputs. As I may have to run a lot of process (up to 20), and I don't want to saturate bandwidth, i'll run 5 in parallel max. Every time a process finishes, I increment the progress counter (for my progress bar) and I run another one until they're all completed, using :
Process p = new Process();
p.StartInfo.FileName = pathToApp;
p.EnableRaisingEvents = true;
p.Exited += OnCalibrationProcessExited;
p.Start();
private void OnCalibrationProcessExited(object sender, EventArgs e)
{
runAnotherOne function
}
Is it correct or is there a more elegant way to achieve this ?
I don't want my app to be blocked during execution of course.
Is it better to use background workers for this ?
You should be using Process and ProcessStartInfo.
You'll need to set ProcessStartInfo.UseShellExecute to false, ErrorDialog to false, RedirectStandardOutput to true (and possibly RedirectStandardError too).
You'll also need to provide a delegate to the Process object to handle to output generated by the external process through OutputDataReceived (and possibly ErrorDataReceived as well).
There's also an Exited delegate you can set that will be called whenever the process exits.
Example:
ProcessStartInfo processInfo = new ProcessStartInfo("Write500Lines.exe");
processInfo.ErrorDialog = false;
processInfo.UseShellExecute = false;
processInfo.RedirectStandardOutput = true;
processInfo.RedirectStandardError = true;
Process proc = Process.Start(processInfo);
proc.ErrorDataReceived += (sender, errorLine) => { if (errorLine.Data != null) Trace.WriteLine(errorLine.Data); };
proc.OutputDataReceived += (sender, outputLine) => { if (outputLine.Data != null) Trace.WriteLine(outputLine.Data); };
proc.BeginErrorReadLine();
proc.BeginOutputReadLine();
proc.WaitForExit();
Just waiting for each thread to end before updating the progress bar results in nothing happening ... then a quick jump .. 3 times. You may as well skip the progress bar.
The correct way to do it IMHO would be to calculate the toal work done across all 3 process:
totalwork = time1 + time2 + time3
Now, if you have multiple processors, it will take more like max(time1, time2, time3) but thats ok. It's a representation of work.
Have a shared variable for work-done. Each time a process does some more work, update the progress bar by calculating work-done += my-work-increment. The progress is just work-done/totalwork.
This will give good results regardless of whether the threads run sequentially or in parallel. Since you don't know how things are going to run (you might have a single processor cpu) this is the best approach.
Just create several instances of the Process class by calling the constructor, set the properties to redirect output stream, and then start them.
Your program won't wait for the called process to exit, as long as you don't call the WaitForExit method. No multi-threading is required.
Create a single thread.
In that thread (pseudocode):
Thread begins here
for each externalApp
Run the application with redirect output
Wait for exit
Update progress bar
end for
Thread ends here
See http://msdn.microsoft.com/en-us/library/ty0d8k56.aspx for wait for exit
Or... do you want to run the external apps in parallel?
Edit: based on the latest updates in the orginal post:
If you don't know the actual progress then don't use a regular progress bar. How about an infinite progress bar or a "working" icon?
An infinite progress bar could be a progress bar that fills up and the starts from beginning until everything is done. A working icon is like the Windows busy cursor (the ever spinning circle).
How about creating an ObservableCollection of TaskProgressInfo,
where TaskProgressInfo is a custom class, to which you write your progress.
Bind a WPF listview to that collection, using a datatemplate (with target type = TaskProgressInfo) to show a progressbar for each item (task).
Create an array of BackgroundWorkers that launch the external app and monitor it.
Each background worker should update its TaskProgressInfo, thus updating the datasource of a progressbar.
Upon completion each BackgroundWorker should remove its TaskProgressInfo from the ObservableCollection, thus removing a progress bar from the UI.
Since BackgroundWorker uses the background (UI) thread for report progress and completion,
the changes to the ObservableCollection will be done by its creating thread (thread safe).
Behind the scenes, .NET will use a ThreadPool - some backgroundworkers will share threads.

How do I communicate between multiple threads?

I'm writing a plug-in for another program which uses the native program to open a series of files to extract some data from. One problem I am having is the process takes a long time and I want to keep the user interface from hanging. Plus I also want to give the user the ability to cancel the process before it completes. In the past I've used a background worker for this type of thing, but in this case I don't think a BackgroundWorker will work.
To create a plug-in through the API I am using one can create a custom command by inheriting from an IAPICommand interface. This interface includes an Execute(Application app) method. The class is then instantiated and the Execute() method is called by the program when the user evokes the custom command in the program.
The Execute() method is passed a reference to the current Application object when it is called, and it is this application object that is used to open the files to extract data from. However, the application instance is not able to open a document when requested by a thread other the the original Execute() thread.
So typically the UI would exist on the main thread, and the time consuming data extraction would be performed on a secondary thread. However, in this case the data extraction must be performed on the main thread, and I need to create a secondary thread for the UI.
Here's a stripped down version of the code.
class MyCommand:IAPICommand
{
public void Execute(Application app) // method from IAPICommand
{
Thread threadTwo= new Thread(ShowFormMethod);
threadTwo.Start();
}
public void ProcessWidget(Widget w, Application app)
{
//uses an App to work some magic on C
//app must be called from the original thread that called ExecuteCommand()
}
//method to open custom form on a seperatethread
public void ShowFormMethod()
{
MyForm form = new MyForm();
form.ShowDialog();
}
}
Here is a flow chart that shows how I think this should ultimately work.
alt text http://dl.dropbox.com/u/113068/SOMLibThreadingDiagram.jpg
Does this diagram make any sense, and if so am I even taking the correct approach to solve this problem?
Once the main thread starts the UI thread I want it to wait for the user to either select widgets to process, or end the command by closing the form (the red figures on the diagram). How can I make the main thread wait, and how do I trigger it to continue either with processing or to continue to the end when the UI thread ends? I was thinking I could have the main thread wait on a Monitor lock. The UI thread would then populate a static list of Widgets to be processed, and then pulse the main thread to trigger the processing. The UI thread would also pulse the Main thread when the form is closed, and the main thread would know to continue to the end of the command if it was ever pulsed when the list of widgets to process was empty.
How do I allow the main thread to communicate the progress or completion of widget processing back to the UI thread (yellow arrows in the diagram)? Do I just used the BeginInvoke() method of the Form to do this?
How do I allow the UI thread to cancel the widget processing (green arrow in the diagram)? I think I could just setup a static Boolean flag that is checked before each widget is processed?
It's generally a bad idea to have multiple threads in your application that each create forms. It isn't impossible to make this work, but it's much harder than you think it will be because forms that are in a parent-child relationship send messages to each other, and when they do, the one sending the message blocks until the one receiving handles it.
Mix this in with the message passing or synchronization between threads that you are doing explicitly, and it's easy to end up with deadlocks. So, in general, you are better off making sure that you reserve your main thread for your user interface, and do all processing in other threads that have no UI.
If you conform to that design, then the background threads can use Control.BeginInvoke to pass messages to the UI thread without having to wait for the messages to be processed.
In addition to the other answers, I recommend that you use a callback method from ProcessWidget to pass progress back to the calling thread. To prematurely stop the worker thread, you can use the callback to return a halt signal to your worker thread if it updates the caller often enough. Or use a separate callback method to periodically check for go/no-go. Or set a (gasp!) global static flag that the worker periodically checks. Or call Thread.Abort on the worker thread and have it catch the ThreadAbortException to clean up any resources.
I assume that the host application is a WinForms app.
You need to save the SynchronizationContext from the original thread in your Execute method, then call its Send method to execute code on the host's UI thread.
For example:
class MyCommand:IAPICommand
{
SynchronzationContext hostContext;
public void Execute(Application app) // method from IAPICommand
{
hostContext = SynchronzationContext.Current;
Thread threadTwo = new Thread(ShowFormMethod);
threadTwo.Start();
}
public void ProcessWidget(Widget w, Application app)
{
//uses an App to work some magic on C
//app must be called from the original thread that called ExecuteCommand()
SomeType someData = null;
hostContext.Send(delegate { someData = app.SomeMethod(); }, null);
}
}
If you look at Java swing, it is a nice example of how to do this:
1) A main thread is responsible for handling all UI requests. This removes any race conditions from the app.
2) Any time any "work" is to be done, spawn a thread (or a thread pool) and do the work. Thus the main thread is not held up except for a few microseconds and the UI is completely responsive while whatever is going on.
3) In all languages there has to be a thread interrupt mechanism. In java you invoke .interrupt() on the thread, and the current running thread gets a InterruptedException thrown wherever it is executing. You job is to catch that exception, figure out if you are really interrupted (read javadocs for this part) and if you are just let yourself die (return out of the run method).
1 + 2 = unobtrusive client interaction
3 = killing threads
An alternative to 3 (if 3 is too complex) is to give the thread a method .kill(); the method sets a kill flag. When you are reading a buffer from the hard drive in a loop, check if the kill flag is set, if it is then break out of the loop, close handlers, and return out of the run method.
Edit: sorry forgot to mention progress report:
Your thread should have a publicly exposed thread-safe method of getting the "progress report" or rather a data structure containing information about progress. Your UI thread should periodically (say every .5 seconds) check the thread's progress report and update the UI's progress bar. And by UI thread checking I mean your widget that shows the progress makes a request to re-render with the latest information on a timer, until done.

Categories

Resources