標籤:c# thread suspend resume
我本質是不希望有人去掛起或恢複線程的,因為沒人知道線程到底執行到了那裡,
掛起線程後再恢複線程可能會造成某些問題,然後你容易無法解決它,所以微軟
如今是把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方案,當然還有一些辦法。總之掛起或恢複
一個線程的辦法並不少 上面的三種方法其實都可以 不過需要考慮穩定性才是真。
C# 線程的掛起與恢複