Which threading model is best for this scenario: I have a process can take several minutes to complete and once it starts I have no control of the 开发者_高级运维code that runs. The process will either error out or return results.
I would like to allow the user to cancel the process. I don't need the process to report its progress, only that it completed or there was an error. There's no clean up required if the process is canceled.
I looked at the various threading options and noticed to add cancellation it seems I need to implement some sort of cancellation flag in the running code which isn't possible in my case. It's also not practical to add a thread timeout. I thought about running my process in an AppDomain but get the feel that this approach may be a deadend.
Using C# 3.5 Winform.
Actually a separate AppDomain or Process is the only safe way to cancel it. Thread.Abort() is very unsafe, is it dis-advised.
There is Thread.Abort(), but it is not guaranteed to kill the thread. What it does is raise a ThreadAbortException in the thread, which won't necessarily kill the thread depending what it is doing, like a finally {} block.
It's always better to put in some kind of cooperative flag the thread inspects and gracefully cleans up and exits upon seeing, but if you don't have a choice, Thread.Abort() is about it. Beware that if the thread code is setting locks and such, they are not going to get cleaned up unless the thread has logic to handle the ThreadAbortException and clean them up.
Declare a flag in your thread (e.g. bool killme) and set it to false. And have a look at a Timer in System.Threading to poll the the value of this flag. If true, exit the thread. This timer needs to be created by the thread during its initialisation.
It will be executed during your thread process as you want and by the thread, meaning the thread knows he needs to be stopped and can do some actions before leaving (like closing opened files, etc.).
If you are running your process in a separate thread that you ran up you could call Thread.Abort on it. There are a LOT of reasons why Thread.Abort should not be used though so read the warnings carefully.
The quick and dirty way is to use the kernel and platform invoke.
[System.Runtime.InteropServices.DllImport("kernel32.dll")]
static extern IntPtr OpenThread(uint dwDesiredAccess, bool bInheritHandle, uint dwThreadId);
[System.Runtime.InteropServices.DllImport("kernel32.dll")]
static extern bool TerminateThread(IntPtr hThread, uint dwExitCode);
Obtain the pointer from OpenThread and use it in TerminateThread. You will need to use the threadID from your thread for the last argument to OpenThread.
Be warned, this is usually a very bad idea, though sometimes dirty is better than non-existence.
Also, I say this because I assume that you cannot use a cancelation flag. If you can, that is always the best method. I have a sample on my blog.
http://memmove.blogspot.com/2011/04/treating-thread-as-service.html
精彩评论