如果你在一个线程里用 lock语法 锁住了某段数据,当外部粗暴的 abort 或 interrupt 这个线程后,退出线程前,这个 lock 会自动释放了。
我做了一个简单的例子来模拟情况,先是写了一个 类 Class2,里面有一个 int _count 用来在线程间互斥的修改,用一个 _locker 来保护。
提供了四个方法:
start(),创建线程并运行。运行起来,先会用 lock(_locker) 加锁保护,在保护内 _count 加1,然后,就sleep这个线程1小时。1小时到期后,会退出锁保护。
abort(),interrupt(),都会触发上面那个线程中断。
add(),先会用 lock(_locker) 加锁保护,在保护内 _count 加1,再退出锁保护。
然后创建一个FORM,在这个FORM 上有四个按键,一个是创建线程并运行(start thread),另一个是 abort 这个线程,还有一个是 interrupt 这个线程,最后一个是 add 一个值。注意因为 add 时会被锁住,所以,add 这里又创建一个线程去 调用 上面那个类里的 add,这样,界面上的 add 就可以反复按而不住卡住 FORM 主线程。
这是那个 Class2.cs。
using System; using System.Threading; using System.Diagnostics;namespace testThreadForm {public class Class2{private object _locker = new object();private Thread _t = null;private int _count = 0;public void Start(){Debug.WriteLine("[{0}] Start: BEGIN.", Thread.CurrentThread.ManagedThreadId);if (null != _t){_t.Abort();_t.Join();_t = null;}_t = new Thread(new ThreadStart(_backgroundLoop));_t.Start();Debug.WriteLine("[{0}] Start: END.", Thread.CurrentThread.ManagedThreadId);}public void Interrupt(){Debug.WriteLine("[{0}] Interrupt: BEGIN.", Thread.CurrentThread.ManagedThreadId);if (null != _t){_t.Interrupt();}Debug.WriteLine("[{0}] Interrupt: END.", Thread.CurrentThread.ManagedThreadId);}public void Abort(){Debug.WriteLine("[{0}] Abort: BEGIN.", Thread.CurrentThread.ManagedThreadId);if (null != _t){_t.Abort();}Debug.WriteLine("[{0}] Abort: END.", Thread.CurrentThread.ManagedThreadId);}public void Add(){Debug.WriteLine("[{0}] Add: BEGIN.", Thread.CurrentThread.ManagedThreadId);lock (_locker){++_count;Debug.WriteLine("[{1}] ADD: count = {0}", _count, Thread.CurrentThread.ManagedThreadId);}Debug.WriteLine("[{0}] Add: END.", Thread.CurrentThread.ManagedThreadId);}private void _backgroundLoop(){Debug.WriteLine("[{0}] Loop: BEGIN.", Thread.CurrentThread.ManagedThreadId);try{lock (_locker){_count++;Thread.Sleep(1000 * 60 * 60);}}catch (ThreadInterruptedException){Debug.WriteLine("[{0}] Loop: ThreadInterruptedException awoken.",Thread.CurrentThread.ManagedThreadId);}catch (ThreadAbortException){Debug.WriteLine("[{0}] Loop: ThreadAbortException aborted.",Thread.CurrentThread.ManagedThreadId);}finally{Debug.WriteLine("[{0}] Loop: END.", Thread.CurrentThread.ManagedThreadId);}}} }
这是 主 FORM 里的调用。
using System; using System.Diagnostics; using System.Threading; using System.Windows.Forms;namespace testThreadForm {public partial class Form1 : Form{Class2 c = new Class2();public Form1(){InitializeComponent();}private void button1_Click(object sender, EventArgs e){c.Start();}private void button2_Click(object sender, EventArgs e){c.Abort();}private void button3_Click(object sender, EventArgs e){Thread t = new Thread(new ThreadStart(_add));t.Start();}private void _add(){Debug.WriteLine("[{0}] _add: BEGIN", Thread.CurrentThread.ManagedThreadId);c.Add();Debug.WriteLine("[{0}] _add: END", Thread.CurrentThread.ManagedThreadId);}private void button4_Click(object sender, EventArgs e){c.Interrupt();}} }
这是按如下操作后的结果:
1)按下 start thread
2)按下 add
3)按下 abort
4)按下 start thread
5)按下 add
6)按下 interrupt
[1] Start: BEGIN. [1] Start: END. [3] Loop: BEGIN. [4] _add: BEGIN [4] Add: BEGIN. [1] Abort: BEGIN. Exception thrown: 'System.Threading.ThreadAbortException' in mscorlib.dll [4] ADD: count = 2 [3] Loop: ThreadAbortException aborted. Exception thrown: 'System.Threading.ThreadAbortException' in testThreadForm.exe [4] Add: END. [3] Loop: END. [1] Abort: END. The thread 0x6578 has exited with code 0 (0x0). [4] _add: END The thread 0x2508 has exited with code 0 (0x0).[1] Start: BEGIN. [1] Start: END. [5] Loop: BEGIN. [6] _add: BEGIN [6] Add: BEGIN. [1] Interrupt: BEGIN. [1] Interrupt: END. Exception thrown: 'System.Threading.ThreadInterruptedException' in mscorlib.dll [5] Loop: ThreadInterruptedException awoken. [6] ADD: count = 4 [6] Add: END. [6] _add: END The thread 0x5fc has exited with code 0 (0x0). [5] Loop: END. The thread 0x4994 has exited with code 0 (0x0).