日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

处理WinForm多线程程序时的陷阱(摘自网络)

發布時間:2023/12/31 编程问答 42 豆豆
生活随笔 收集整理的這篇文章主要介紹了 处理WinForm多线程程序时的陷阱(摘自网络) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
與所有的UI開發平臺一樣,.NET下線程開發圖形界面同樣要遵循一個基本原則:就是對UI對象的操作一定要在產生該UI對象的線程里進行(該線程稱作UI線程),因為大部分UI對象都不是線程安全的。

  在.NET中,把調用調用放在UI線程里執行是通過Form類及其子類的Invoke()方法實現的(具體的過程請參考其他資料),可以這樣做是因為Form對象保存了創建它的線程的信息,而且Form類有一個bool類型的屬性InvokeRequired,可以通過它查看當前線程是否為創建該Form對象的線程(UI線程)——如果為true,則表示當前線程不是UI線程,反之則是。下面提供一個例子:

using System.Threading;
using System.Windows.Forms;

namespace csharpTest
{
 public class TestForm : Form
 {
  private Form form1;
  private Form form2;

  public static void Main()
  {
   TestForm tf = new TestForm();
   tf.Show();
   tf.UIThread();
   Application.Run();
  }

  public void UIThread()
  {
   form1 = new Form();
   form2 = new Form();
   form2.Show();//這里是關鍵
   form1.Show();
   Thread thread = new Thread(new ThreadStart(WorkerThread));
   thread.Start();
  }

  public void WorkerThread()
  {
   if (form2.InvokeRequired)
    form2.Invoke(new MethodInvoker(WorkerThread));
   else
   {
    form1.Text = "This is from WorkerThread.";
   }
  }

  protected override void OnClosing(System.ComponentModel.CancelEventArgs e)
  {
   base.OnClosing (e);
   Application.Exit();
  }
 }
}

  TestForm里有兩個需要注意的方法,UIThread——用來模擬UI線程,WorkerThread——用來模擬用戶線程,UIThread中實例化了成員form1與form2,并調用了它們的Show方法,在WorkerThread中改變form1的Text屬性。請注意WorkerThread里有個技巧, if (form2.InvokeRequired) 即如果當前線程不是創建該form2的線程,則將方法通通過過Invoke方法放到UI線程里去執行。但就是這里問題出現了。form1和form2都是在UIThread里建立的,所以它們保存的線程的信息應該是一樣的。所以form1.InvokeRquired和form2.InvokeRquired的值在任何線程里都是一樣的,即在WorkerThread中InvokeRquire的值都應該是true(因為在不同的線程里)。但是如果注釋掉form2.Show()的話form2.InvokeRquired在WorkerThread中的值卻是false(在vs.net中調試看到),怎么會這樣呢?而且如果不經過判斷直接在WorkerThread里調用form2對象的Invoke的話…………居然會拋出異常——“在創建窗口句柄之前,不能在控件上調用 Invoke 或 InvokeAsync”分析一下該異常的信息,在win32里每一個窗體都有一個窗體句柄,是該窗體在建立時系統分配的,但我們確實在UI線程里建立了form2對象的。這里有個誤區.Net里的Form對象并不是和win32的窗體對象完全對應的。

  本人竊以為,產生一個Form類的實例時,只是產生了一個內存中的普通的對象,并不產生系統窗體(好像叫做User對象吧),只有它第一次呈現在屏幕上(或稱作創建)時,才產生系統里表示窗體的User對象且分配句柄,對應的WIN32 API的CreateWindow()方法大概也在這個時候執行(先聲明:本人對WIN32 AP 并不熟悉,所以這里如果有什么不妥的話請大家指正)

  只有.NET里的form對象調用某種方法使系統產生真正的窗體時,form才會有創建它的線程的信息,且InvokeRquired才有效,即才能調用form的Invoke方法。不過我還沒弄清楚哪幾個方法可以做到。據我所知Show, CreateGraphics可以產生系統真正的系統窗體。

轉載于:https://www.cnblogs.com/wzyexf/archive/2007/03/25/687303.html

總結

以上是生活随笔為你收集整理的处理WinForm多线程程序时的陷阱(摘自网络)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。