c#多线程同步之EventWaitHandle的应用
最近在研究前辈写的winform代码,其中有一个功能,前辈用了EventWaitHandle。初读代码,有点不理解,慢慢想来,还是可以理解的。这个功能,就是执行某项比较耗时的任务,需要打开旋转图标,等任务执行完成后,再关闭旋转图标。这是程序主体框架:
1 public void ImportFile(List<string> files) 2 { 3 bool state = true; 4 EventWaitHandle wait = new EventWaitHandle(false, EventResetMode.ManualReset); 5 EventWaitHandle loadWait = new EventWaitHandle(false, EventResetMode.ManualReset); 6 7 Thread thread = new Thread(delegate(object obj) 8 { 9 loadWait.WaitOne(); 10 EventWaitHandle waitHandle = obj as EventWaitHandle; 11 12 try 13 { 14 //执行比较耗时的任务 15 } 16 catch 17 { 18 state = false; 19 } 20 waitHandle.Set(); 21 }); 22 23 thread.Start(wait); 24 new OperationTip().ShowWait(wait, loadWait, MainForm._MainForm); 25 26 if (!state) 27 { 28 new ServerErrorInformation().ShowDialog(MainForm._MainForm); 29 return; 30 } 31 }
解释:线程(给个名称:TaskThread)启动后(23行),被阻塞了(第9行loadWait.Wait() )。那什么时候解除阻塞呢?24行实例化了一个OperationTip对象,而且调用了ShowWait方法,我想秘密就在这个类里面:
public partial class OperationTip : Form { public delegate void CloseThis(); EventWaitHandle loadWait = null;public OperationTip() { InitializeComponent(); this.Icon = Resources.NoteFirst; this.ptbMain.Image = Resources.SystemProcess_1; this.ShowInTaskbar = false; }private void OperationTip_Load(object sender, EventArgs e) { if (point.X == 0 && point.Y == 0) { this.StartPosition = FormStartPosition.CenterParent; } else { this.Location = new Point(point.X, point.Y); } if (loadWait != null) loadWait.Set(); } public void ShowWait(EventWaitHandle wait, EventWaitHandle loadWait, IWin32Window window) { this.loadWait = loadWait; ThreadPool.QueueUserWorkItem(delegate { wait.WaitOne(); if (this.InvokeRequired) { this.Invoke(new CloseThis(CloseThisForm)); } else { CloseThisForm(); } }); this.ShowDialog(window); } public void CloseThisForm() { this.Close(); } }
很有意思的是 ShowWait方法里,又开启了一个线程(起个名称:closeThread),这个线程专门负责关闭当前的旋转图标(OperationTip 窗体,整个窗体看起来就是一个旋转图标)。此线程目前被阻塞,ShowDialog方法调用后,OperationTip_Load方法才开始执行,此时 loadWait.Set(),让TaskThread 才开始执行,等执行完了,第20行 waitHandle.Set()方法的执行,它解除了closeThread线程的阻塞,让closeThread线程继续运行,那么旋转图标就被关闭了。