I have an application that uses 20 threads. It's an email client that uses threads to mail from.
Currently the threads are created in the main thread. But I am wondering, what if I want to cancel the whole operation? The only way I can see of doing it is killing the main thread ... thus ending the program.
Would I have to create a thread that encapsulates the threads for mailing so I can kill the encapsulating thread?
I am currently using BackgroundWorker by the way and it's a WF application.
If you are using a BackgroundWorker then you already have all of the infrastructure you need to cancel the operation. Simply set WorkerSupportsCancellation to true on the BackgroundWorker, and invoke the worker's CancelAsync method when you want to cancel.
Obviously you have to write the worker code to honour the cancellation. You do this by checking the CancellationPending property of the BackgroundWorker.
MSDN has an example of using this property.
Note - I am a bit confused by the combination of BackgroundWorker and 20 threads; a BackgroundWorker only uses one thread by itself. Are you spinning off 20 BackgroundWorkers? If so, how do you ensure that they're properly disposed? If you need that much concurrency in a Winforms app then it's better to use asynchronous delegates or the Thread Pool.
If you are creating actual threads, one common way of implementing a cancellation flag is to use a ManualResetEvent. If you wait on this event with zero timeout, it acts as a thread-safe status flag. An example usage would be:
ManualResetEvent cancelEvent = new ManualResetEvent(false);
for (int i = 0; i < 20; i++)
{
ThreadPool.QueueUserWorkItem(s =>
{
// Do some work
if (cancelEvent.WaitOne(0, true))
return;
// Do some more work
// etc.
});
}
Then at some point later if you write cancelEvent.Set(), every worker will stop its work as soon as it hits the status check.
Related
I am using BackgroundWorker for processing a long running external operation. However the user have option to cancel the background operation. Since my custom BackgroundWorker supports Thread.Abort(), all I am doing is BackgroundWorker.Abort() when user triggers Cancel from main thread.
But the thread is not actually terminating, it is still completing the external process. Is there any way I can terminate a thread instantly.
I do not have control on the external processing, so cannot send any flag for approach like while (checkThreadCancelled){}.
Below is my pseudo code.
Any help?
AbortableBackgroundWorker _bgWorker;
void MainThreadFunc()
{
_bgWorker = new AbortableBackgroundWorker();
_bgWorker.DoWork += new DoWorkEventHandler(bg_DoWork);
_bgWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler
( bg_RunWorkerCompleted );
_bgWorker.WorkerSupportsCancellation = true;
_bgWorker.RunWorkerAsync();
}
void bg_DoWork()
{
//Call external dll function for processing
}
void bg_RunWorkerCompleted()
{
//Process completed code
}
void CancelBgProcess()
{
if(_bgWorker != null)
_bgWorker.Abort();
}
The Abort method relies on worker thread cooperating with it. Ultimately it causes the CLR to throw an exception indicating that the thread is to abort, which the thread is free to deal with as it pleases.
As your worker thread is executing something in a DLL, the CLR isn't in control and therefore it does not have the option to throw an exception.
You have the option of using the Win32 TerminateThread API, but doing so is severe and may or may not lead to corruption within your process. TerminateThread is not really an option that you should ever choose.
Since you cannot modify the library that you are calling, you are left with two options. The first and easiest approach, lower the priority of the background thread and ignore the fact that it continues to run after cancellation.
The second is to launch your background operation in a separate process rather than thread. At which point, you may terminate the entire process if the operation is cancelled. If you go this route, you will need to pick some form of IPC to communicate the input and output parameters of the library.
Tasks and CancellationTokens ultimately will not help you in this situation as you will end up in the same place: executing library code that will not cooperate with you in order to be cancelled.
You don't want to use Thread.Abort, it is typically considered bad practice. There are many questions asked on SO that provide some very good explanations. For example: Timeout Pattern - How bad is Thread.Abort really?
Try looking at Tasks and CancellationTokens. See this MSDN article: http://msdn.microsoft.com/en-us/library/dd997396.aspx
Try this:
if (_bgWorker.IsBusy)
{
_bgWorker.WorkerSupportsCancellation = true;
//To cancel the Thread if Closing the Application
//while the Background Thread Worker is Still running on Background.
_bgWorker.CancelAsync();
}
It will stop the current thread process and will cancel the ongoing operation on that thread.
May be it helps you
Here's what I woulld like to do:
Create a worker thread in my main thread (which controls the UI).
The worker thread keeps running until shut down by the main thread (which only happens when the entire application is shut down).
The main thread listens for keyup, but sends an event to the worker thread to process the keyup asynchronously (to avoid blocking the UI).
The worker thread updates the UI when the keyup has been handled.
So far I've just been creating a new thread every time there is a keyup, but it seems there is just too much overhead this way.
As far as I can tell, I should use the BackgroundWorker class, but the examples I've seen seems to start a background worker, continue with non-blocked UI in the main thread and update UI from the BackgroundWorker when it's finished - i.e. exactly the same as I'm already doing.
How to make it so the worker thread keeps running and sleep when there is no work to be done?
While Zaches answer is completely valid (and an approach I used for some time) I've stumbled upon what I think is a more elegant solution using Dispatcher:
Create the worker thread:
Dispatcher _workerDispatcher;
Thread _workerThread = new Thread(new ThreadStart(() =>
{
_workerDispatcher = Dispatcher.CurrentDispatcher; // Required to create the dispatcher
Dispatcher.Run(); // Keeps thread alive and creates a queue for work
});
_workerThread.Start();
Put work into the worker thread (from main thread or another thread):
// Synchronous work
_workerDispatcher.Invoke(() =>
{
// Do stuff
});
// Asynchronous work (makes most sense for background work)
_workerDispatcher.BeginInvoke(() =>
{
// Do stuff
});
Shut down the worker thread:
_workerDispatcher.InvokeShutdown();
_workerThread.Join(); // Wait for thread to shut down
I'm using new Thread() because I need to set apartment state, but you can also use tasks created using Task.Run() and Task.Factory.StartNew().
I'm not 100% certain that it's necessary to call thread.Join(), but I'd rather be certain that the thread has been shut down. If you're using a Task call task.Wait() instead.
Another way to get the Dispatcher is to call Dispatcher.FromThread(thread), but it's important to note that a Dispatcher is NOT created until CurrentDispatcher has been used (even if you don't use the reference later).
A downside of this approach is that it can't be used to have multiple threads pick items out of a queue and do work - for that you will have to use the producer/consumer approached described in Zaches answer. The dispatcher approach allows you to queue up work in a specific thead.
Why don't you just use the Task Parallel Library?
Create a new task whenever you detect the KeyUp event, and let TPL worry about creating new threads. Since it uses the thread pool, a new thread will not be created every time an event is fired.
The problem you are having is called the Producer/Consumer problem. And you can solve it easily using any of the ConcurrentCollections available.
Try something like this:
var queue = new ConcurrentQueue<string>();
var consume = true;
var producer = Task.Run(() =>
{
var input = Console.ReadLine();
while(!string.IsNullOrEmpty(input)
{
queue.Enqueue(input);
input = Console.ReadLine();
}
});
var consumer = Task.Run(() =>
{
while(consume) //So we can stop the consumer
{
while(!queue.IsEmpty) //So we empty the queue before stopping
{
stringres;
if(queue.TryDequeue(out res)) Console.WriteLine(res);
}
}
});
await producer;
consume = false;
await consumer;
Try using the Task Pattern Library instead of manually starting up threads. It is your friend.
In my application I am start process (Tshark) and start capturing, after I am finish to capturing I am checking the created file and parse from the process output the number of received packets in order to update my UI.
in this point if the created file is big all the UI stuck until the result on number of packets received so I want to do it in different Thread.
Capinfos capInfo = new Capinfos(); //my class who return the number of packets
ThreadStart tStarter = delegate {label.Text = capInfo._numberOfPackets.ToString("#,##0"); };
Thread thread = new Thread(tStarter);
thread.IsBackground = true;
thread.Start();
This code return a cross threading error.
You're doing it the wrong way round. You should be performing the packet capture in a different thread, only accessing the UI elements within the UI thread.
There are loads of different ways of doing this. The most common are probably:
You can use Control.Invoke and Control.BeginInvoke to marshal back to the UI thread when you need to
You can use BackgroundWorker which does some of this for you; you'd hook up the progress reporting event to update the UI from the right thread
If you're using C# 5 and .NET 4.5 you could use async/await to automatically get back to the UI thread within a single asynchronous method
It appears that you're trying to update the UI using a thread other than the UI thread (label.Text = ---). I think that is probably what the problem is. You could use Tasks to achieve asynchrony. You could use the Task's ContinueWith method to wait on the task to finish before updating your UI thread using BeginInvoke.
http://msdn.microsoft.com/en-us/library/dd235678.aspx
(the following items has different goals , but im interesting knowing how they "PAUSEd")
questions
Thread.sleep - Does it impact performance on a system ?does it tie up a thread with its wait ?
what about Monitor.Wait ? what is the difference in the way they "wait"? do they tie up a thread with their wait ?
what about RegisteredWaitHandle ? This method accepts a delegate that is executed when a wait
handle is signaled. While it’s waiting, it doesn’t tie up a thread.
so some thread are paused and can be woken by a delegate , while others just wait ? spin ?
can someone please make things clearer ?
edit
http://www.albahari.com/threading/part2.aspx
Both Thread.Sleep and Monitor.Wait put the thread in the WaitSleepJoin state:
WaitSleepJoin: The thread is blocked. This could be the result of calling
Thread::Sleep or Thread::Join, of requesting a lock — for example, by
calling Monitor::Enter or Monitor::Wait — or of waiting on a thread
synchronization object such as ManualResetEvent.
RegisteredWaitHandle is obtained by calling RegisterWaitForSingleObject and passing a WaitHandle. Generally all descendants of this class use blocking mechanisms, so calling Wait will again put the thread in WaitSleepJoin (e.g. AutoResetEvent).
Here's another quote from MSDN:
The RegisterWaitForSingleObject method checks the current state of the
specified object's WaitHandle. If the object's state is unsignaled,
the method registers a wait operation. The wait operation is performed
by a thread from the thread pool. The delegate is executed by a worker
thread when the object's state becomes signaled or the time-out
interval elapses.
So a thread in the pool does wait for the signal.
Regarding ThreadPool.RegisterWaitForSingleObject, this does not tie up a thread per registration (pooled or otherwise). You can test this easily: run the following script in LINQPad which calls that method 20,000 times:
static ManualResetEvent _starter = new ManualResetEvent (false);
void Main()
{
var regs = Enumerable.Range (0, 20000)
.Select (_ => ThreadPool.RegisterWaitForSingleObject (_starter, Go, "Some Data", -1, true))
.ToArray();
Thread.Sleep (5000);
Console.WriteLine ("Signaling worker...");
_starter.Set();
Console.ReadLine();
foreach (var reg in regs) reg.Unregister (_starter);
}
public static void Go (object data, bool timedOut)
{
Console.WriteLine ("Started - " + data);
// Perform task...
}
If that code tied up 20,000 threads for the duration of the 5-second "wait", it couldn't possibly work.
Edit - in response to:
"this is a proof. but is there still a single thread which checks for
signals only ? in the thread pool ?"
This is an implementation detail. Yes, it could be implemented with a single thread that offloads the callbacks to the managed thread pool, although there's no guarantee of this. Wait handles are ultimately managed by operating system, which will most likely trigger the callbacks, too. It might use one thread (or a small number of threads) in its internal implementation. Or with interrupts, it might not block a single thread. It might even vary according to the operating system version. This is an implementation detail that's of no real relevance to us.
While it's true RegisterWaitForSingleObject creates wait threads, not every call creates one.
From MSDN:
New wait threads are created automatically when required
From Raymond Chen's blog:
...instead of costing a whole thread, it costs something closer to (but not exactly) 1/64 of a thread
So using RegisterWaitForSingleObject is generally preferable to creating your own wait threads.
Thread.Sleep and RegisteredWaitHandle work at different levels. Let me try and clear it up:
Processes have multiple threads, which execute simultaneously (depending on the OS scheduler). If a thread calls Thread.Sleep or Monitor.Wait, it doesn't spin - it is put to WaitSleepJoin state, and the CPU is given to other threads.
Now, when you have many simultaneous work items, you use a thread pool - a mechanism which creates several threads, and uses its own understanding of work items to dispatch calls to its threads. In this models, worker threads are called from the thread pool dispatcher to do some work, and then return back to the pool. If a worker thread calls a blocking operation - like Thread.Sleep or Monitor.Wait - the this thread is "tied up", since the thread pool dispatcher can't use it for additional work items.
I'm not familiar with the actual API, but I think RegisteredWaitHandle would tell the thread pool dispatcher to call a worker thread when needed - and your own thread is not "tied up", and can continue its work or return to the thread pool.
ThreadPool.g RegisterWaitForSingleObject does call in its native implementation ultimately
QueueUserAPC. See rotor sources (sscli20\clr\src\vm\win32threadpool.cpp(1981)). Unlike Wait Thread.Sleep your thread will not be put to a halt when you use RegisterWaitForSingleObject.
Instead for this thread a FIFO queue with user mode callbacks is registered which will be called when the thread is in an alertable state. That means you can continue to work and when your thread is blocked the OS will work on the registered callbacks giving your thread do to the opportunity to do something meaningful while it is waiting.
Edit1:
To complete the analysis. On the thread that did call RegisterWaitForSingleObject a callback is called on the thread when it is in an alertable state. Once this happens the the thread that did call RegisterWaitForSingleObject will execute a CLR callback that does register another callback which is processed by a thread pool callback wait thread which is only there to wait for signaled callbacks. This thread pool callback wait thread will then check in regular intervals for signaled callbacks.
This wait thread does finally call QueueUserWorkItem for the signalled callback to be executed on a thread pool thread.
I'm working on a multi-threaded Silverlight application.
The application has two threads: Main/UI and a background working thread.
The UI thread should be able to kill the background thread, like so:
private Thread executionThread;
....
executionThread = new Thread(ExecuteStart);
executionThread.Start();
....
executionThread.Abort(); // when the user clicks "Stop"
The last line raises an Exception:
MethodAccessException: Attempt to access the method failed: System.Threading.Thread.Abort()
Any idea? why i cannot abort a thread in Silverlight?
Thanks,
Naimi
Rather than creating a Thread manually for this purpose you might want to consider using the BackgroundWorker class.
This class has built in functionality for cancelling the asynchronous operation when WorkerSupportsCancellation = true.
Have a look at this article on MSDN for a full example of how to use the BackgroundWorker in Silverlight.
It's documented, see Thread.Abort()
This member has a
SecurityCriticalAttribute attribute,
which restricts it to internal use by
the .NET Framework for Silverlight
class library. Application code that
uses this member throws a
MethodAccessException.
You could use a ManualResetEvent (a thread safe communication method) to signal the background thread to stop.
Example code in the background thread:
if (!shouldStop.WaitOne(0))
// you could also sleep 5 seconds by using 5000, but still be stopped
// after just 2 seconds by the other thread.
{
// do thread stuff
}
else
{
// do cleanup stuff and exit thread.
}
Since Silverlight code comes across the Internet, it is generally untrusted, and its execution is more restricted, as Davy pointed out.
Rather, implement a boolean exit flag in the class that is canonical for the background thread, so that you can raise this flag and use Thread.Join() instead.