当前位置: 代码迷 >> C# >> C# 线程的挂起与回复
  详细解决方案

C# 线程的挂起与回复

热度:70   发布时间:2016-05-05 03:20:56.0
C# 线程的挂起与恢复

我本质是不希望有人去挂起或恢复线程的,因为没人知道线程到底执行到了那里,

挂起线程后再恢复线程可能会造成某些问题,然后你容易无法解决它,所以微软

如今是把Thread.Resume()与Thread.Suspend()过时,不久以后会移除出.NET库

但是移除你就无法挂起或恢复了吗?我想是不可能 毕竟办法如此之多 好了我们回

到正题 如果你有必要这样做我也希望你们用AutoResetEvent(自动重置单事件对象)

的配合,因为它会很安全 但是能否够安全还需要具体看开发者自己的代码如何写的。

        private void Form1_Load(object sender, EventArgs e)        {            Thread fd_thr = new Thread(this.FileDownload);            fd_thr.Start();            fd_thr.Suspend(); // 挂起线程, 过时            fd_thr.Resume();  // 恢复线程, 过时        }        private void FileDownload()        {            byte[] buffer = null;            using (WebClient client = new WebClient())                buffer = client.DownloadData("http://www.baidu.com");            Console.WriteLine(Encoding.UTF8.GetString(buffer));        }
下面的代码,貌似没有问题,但你可能会在输出面板会出现一句错误“引发的异常:

“System.IO.IOException”(位于 mscorlib.dll 中)”那么这就会涉及到一个问题,我本

人是讨厌代码抛出错误的,首先你要知道一但抛出错误意味着无法释放资源且不

最重要抛出错误的频率过高你的程序意味着稳定性极差不一会可能就会自己挂

掉,每次抛出错误意味着一次堆栈溢出,try catch尽量少用,为什么需要自己体会

        private AutoResetEvent fd_thr_supend = new AutoResetEvent(false);        private void Form1_Load(object sender, EventArgs e)        {            Thread fd_thr = new Thread(this.FileDownload);            fd_thr.Start();            this.fd_thr_supend.Reset(); // 挂起线程            this.fd_thr_supend.Set(); // 恢复线程        }        private void FileDownload()        {            byte[] buffer = null;            using (WebClient client = new WebClient())                buffer = client.DownloadData("http://www.baidu.com");            this.fd_thr_supend.WaitOne(); // 阻塞,等待信号            Console.WriteLine(Encoding.UTF8.GetString(buffer));        }
上面则配合AutoResetEvent方式配合进行线程的挂起或恢复,这样做有利代码的

安全与减少发生错误的几率,因为你不是真正的把线程挂起而是阻塞线程 那么一

旦发生错误 你可以尽早的排查错误,而不是因为Thread.Resume()与Thread.Sus

pend()方式一挂起,一旦发生错误你根本找不到错误的原因,大大的增加了稳定

性与安全性。

        [DllImport("kernel32.dll", SetLastError = true)]        private static extern int GetCurrentThreadId();        [DllImport("kernel32.dll", SetLastError = true)]        private static extern int SuspendThread(IntPtr hThread);        [DllImport("kernel32.dll", SetLastError = true)]        public static extern uint ResumeThread(IntPtr hThread);        public int hCurrenthThreadId;        [DllImport("kernel32.dll", SetLastError = true)]        public static extern IntPtr OpenThread(int dwDesiredAccess, bool bInheritHandle, uint dwThreadId);        public const int THREADACCESS_SUSPEND_RESUME = 0x0002;        private void Form1_Load(object sender, EventArgs e)        {            Thread fd_thr = new Thread(this.FileDownload);            fd_thr.Start();            while (this.hCurrenthThreadId == 0); // 等待线程被启动            IntPtr hCurrenthThread = OpenThread(THREADACCESS_SUSPEND_RESUME, false, (uint)this.hCurrenthThreadId);            // 挂起线程            SuspendThread(hCurrenthThread);            // 恢复线程            ResumeThread(hCurrenthThread);         }        private void FileDownload()        {            this.hCurrenthThreadId = GetCurrentThreadId();            byte[] buffer = null;            using (WebClient client = new WebClient())                buffer = client.DownloadData("http://www.baidu.com");            Console.WriteLine(Encoding.UTF8.GetString(buffer));        }
上面的方法也不安全,因为上面的做法其实与Thread.Resume()与Thread.Suspend()两个函数的

功能差不多,不过是用于代替过时命令的一种Winapi方案,当然还有一些办法。总之挂起或恢复

一个线程的办法并不少 上面的三种方法其实都可以 不过需要考虑稳定性才是真。



  相关解决方案