<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    備注學院

    LuLu

      BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::
      5 隨筆 :: 50 文章 :: 16 評論 :: 0 Trackbacks

    訪問 Windows 窗體控件本質上不是線程安全的。如果有兩個或多個線程操作某一控件的狀態,則可能會迫使該控件進入一種不一致的狀態。還可能出現其他與線程相關的 bug,包括爭用情況和死鎖。確保以線程安全方式訪問控件非常重要。

    .NET Framework 有助于在以非線程安全方式訪問控件時檢測到這一問題。在調試器中運行應用程序時,如果創建某控件的線程之外的其他線程試圖調用該控件,則調試器會引發一個 InvalidOperationException,并提示消息:“從不是創建控件 control name 的線程訪問它。”

    有三種方法可以從線程訪問Win窗體的控件:非線程安全方式;線程安全調用;使用BackgroundWorker進行的線程安全調用。其中,只有線程的安全調用可以宏觀并行處理。(另外兩種方式都是在線程運行時接受命令,但在線程執行完以后才執行)。

    一:對Windows窗體控件的非線程安全調用

    該方式是從輔助線程直接調用。調用應用程序時,調試器會引發一個InvalidOperationException,警告對控件的調用不是線程安全的。

    可以通過將 CheckForIllegalCrossThreadCalls 屬性的值設置為 false 來禁用此異常。這會使控件以與在 Visual Studio 2003 下相同的方式運行。

    具體做法如下:

     

    public Form1()
            
    {
                InitializeComponent();
                Control.CheckForIllegalCrossThreadCalls 
    = false;//這一行是關鍵 用于對線程的不安全調用
            }

     

    二:對Windows窗體控件的線程安全調用

    對窗體控件的線程安全調用需要用委托的方式。

    主要思路:

    1、查詢控件的 InvokeRequired 屬性。

    2、如果 InvokeRequired 返回 true,則使用實際調用控件的委托來調用 Invoke。

    3、如果 InvokeRequired 返回 false,則直接調用控件。

    例子:在TextBox控件中輸出相應的信息,SetText為textbox的內容設置方法,SetTextDelegate的委托類型封裝 SetText方法。TextBox控件的InvokeRequired返回true是,SetText方法創建SetTextDelegate的一個實 例,并調用窗體的Invoke方法。是的SetText方法被創建TextBox控件的線程調用。

     

       

      / /該委托使在一個TextBox控件上設置text屬性的異步調用功能為真
            
    delegate void SetTextCallback(string text);

            
    // 該線程用于對Windows窗體控件的安全調用

            
    private Thread demoThread = null;

     

     

    // 該事件句柄創建一個對窗體控件線程安全調用的線程

    private void setTextSafeBtn_Click( object sender,  EventArgs e)
    {
        
    this.demoThread =
            
    new Thread(new ThreadStart(this.ThreadProcSafe));

        
    this.demoThread.Start();
    }


    // 該方法在Worker線程中執行并且發出一個線程安全的調用

    private void ThreadProcSafe()
    {
        
    this.SetText("This text was set safely.");
    }


    //如果被調用的線程和創建的TextBox控件不同,該方法就創建一個SetTextCallback,

    // 并且用Invoke方法異步調用自己。
    // 如果相同,則直接調用方法設置Text的屬性。

    private void SetText(string text)
    {
        
    // 獲取的InvokeRequired將調用的線程ID和創建的線程ID向比較。 
        
    //如果兩個線程ID不同,則返回true 

          
    if (this.textBox1.InvokeRequired)
         
    {   
            SetTextCallback d 
    = new SetTextCallback(SetText);
            
    this.Invoke(d, new object[] { text });
        }

        
    else
        
    {
            
    this.textBox1.Text = text;
        }

    }

    三、使用 BackgroundWorker 進行的線程安全調用
    在應用程序中實現多線程的首選方式是 使用 BackgroundWorker 組件。BackgroundWorker 組件使用事件驅動模型實現多線程。輔助線程運行 DoWork 事件處理程序,創建控件的線程運行 ProgressChanged 和 RunWorkerCompleted 事件處理程序。注意不要從 DoWork 事件處理程序調用您的任何控件。

    下面的代碼示例不異步執行任何工作,因此沒有 DoWork 事件處理程序的實現。TextBox 控件的 Text 屬性在 RunWorkerCompleted 事件處理程序中直接設置。

    private void setTextBackgroundWorkerBtn_Click(object sender,  EventArgs e)
    {
        
    this.backgroundWorker1.RunWorkerAsync();
    }


    private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        
    this.textBox1.Text =
            
    "This text was set safely by BackgroundWorker.";
    }




    posted on 2008-10-31 10:32 smildlzj 閱讀(334) 評論(0)  編輯  收藏 所屬分類: C#
    主站蜘蛛池模板: 一二三四免费观看在线视频中文版 | 亚洲无线观看国产精品| 亚洲熟女综合一区二区三区| 国产在线精品免费aaa片| 亚洲一区二区精品视频| 污网站在线观看免费| 在线视频免费观看www动漫| 亚洲香蕉在线观看| 99久久久精品免费观看国产| 亚洲网址在线观看| 亚洲黄色片免费看| 亚洲国产精品张柏芝在线观看| 999久久久免费精品播放| 亚洲无删减国产精品一区| 91香焦国产线观看看免费| 在线电影你懂的亚洲| 巨波霸乳在线永久免费视频| 国产精品亚洲一区二区三区 | 亚洲不卡av不卡一区二区| 精品一区二区三区免费视频| 亚洲日韩欧洲乱码AV夜夜摸| 久久不见久久见免费影院 | 中文日韩亚洲欧美制服| 日本不卡在线观看免费v| 高潮毛片无遮挡高清免费| 夜夜春亚洲嫩草影院| 美女视频黄的免费视频网页| 亚洲Av无码国产一区二区| 啊v在线免费观看| 好吊色永久免费视频大全| 久久久国产亚洲精品| 亚洲综合无码一区二区| 99在线视频免费观看视频| 成人精品一区二区三区不卡免费看 | 亚洲国产a级视频| 免费观看成人久久网免费观看| 爱情岛亚洲论坛在线观看 | 四虎影永久在线高清免费| 成人免费av一区二区三区| 亚洲日韩在线视频| 亚洲国产精品无码久久一区二区|