Unable to kill a worker thread in Silverlight - c#

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.

Related

Thread "hanging" on Monitor.Wait after Application.Current.ShutDown()

I have a WPF application which used to shutdown via Environment.Exit. Since this caused problems with my automated UI tests, I changed the exiting application to Application.Current.ShutDown.
This works fine, except there is a thread which is waiting to be pulsed (Monitor.Wait), which keeps the process running since it never gets pulsed anymore.
I thought that would be a no brainer to fix, but from the point where my application exits (the Application.Current.ShutDown) it's rather hard to retrieve a reference to the object which holds the waiting thread (in order to force pulse it, so that it can exit).
I tried to google an appropriate answer, but not much luck yet. Is there an "easy way" out of this? Or should I start refactoring already? :)
Some snippets:
Thread is created like this
workerThread = new Thread(Worker) { Name = logName, IsBackground = true};
In the Worker method, Monitor.Wait is called
while ((action = GetNextTask(out task)) == ProductPreparationAction.None)
{
Monitor.Wait(preparationTasks);
}
Nevermind my comment. Start refactoring :).
First of all, there should be a way for the while loop to end when before the app stops. Perhaps you can use and propagate a CancellationToken all the way down to the Worker method.
If you want to keep your loose coupling, you should be able to pulse by creating an event in the class that calls Application.Current.ShutDown and by subscribing to it in the class where the Worker method is (and call Pulse in the event handler).
If you do this, then you can store the CancellationToken in this class and flag it when the event is received.
That event should be raised before calling Application.Current.ShutDown.

Thread Termination suggestion required

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

Canceling Threads

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.

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.

WinForm Application UI Hangs during Long-Running Operation

I have a windows forms application
on which I need to use a for loop having a large number of Remote Calls around 2000 - 3000 calls,
and while executing the for loop, I loose my control on form and form controls, as it becomes a large process and some time it shows "Not Responding" but if I wait for a long it comes back again, I think I need to use some threading model for that, is there any idea, how can I proceed to solve the issue?
You need to perform the long running operation on a background thread.
There are several ways of doing this.
You can queue the method call for execution on a thread pool thread (See here):
ThreadPool.QueueUserWorkItem(new WaitCallback(YourMethod));
In .NET 4.0 you can use the TaskFactory:
Task.Factory.StartNew(() => YourMethod());
And in .NET 4.5 and later, you can (and should, rather than TaskFactory.StartNew()) use Task.Run():
Task.Run(() => YourMethod());
You could use a BackgroundWorker for more control over the method if you need things like progress updates or notification when it is finished. Drag the a BackgroundWorker control onto your form and attach your method to the dowork event. Then just start the worker when you want to run your method. You can of course create the BackgroundWorker manually from code, just remember that it needs disposing of when you are finished.
Create a totally new thread for your work to happen on. This is the most complex and isn't necessary unless you need really fine grained control over the thread. See the MSDN page on the Thread class if you want to learn about this.
Remember that with anything threaded, you cannot update the GUI, or change any GUI controls from a background thread. If you want to do anything on the GUI you have to use Invoke (and InvokeRequired) to trigger the method back on the GUI thread. See here.
private voidForm_Load(object sender, EventArgs e)
{
MethodInvoker mk = delegate
{
//your job
};
mk.BeginInvoke(callbackfunction, null);
}
private void callbackfunction(IAsyncResult res)
{
// it will be called when your job finishes.
}
use MethodInvoker is the easiest way.
Obviously, you need to use background threads. I suggest you read this free e-book.

Categories

Resources