如何跨線程調用.NET Windows表單控制項

來源:互聯網
上載者:User

  本文講解如何使用多安全執行緒地使用.NET 中的Windows表單控制項。

 

  使用多線程提高 Windows 表單應用程式的效能時,必須注意以安全執行緒方式調用控制項。

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

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

 

  此異常在調試期間和運行時的某些情況下可靠地發生。強烈建議您在顯示此錯誤資訊時修複此問題。在調試以 .NET Framework 2.0 版之前的 .NET Framework 編寫的應用程式時,可能會出現此異常。  可以通過將 CheckForIllegalCrossThreadCalls 屬性的值設定為 false 來禁用此異常。這會使控制項以與在 Visual Studio 2003 下相同的方式運行。

 

  對 Windows 表單控制項的非安全執行緒調用方式是從輔助線程直接調用。調用應用程式時,調試器會引發一個 InvalidOperationException,警告對控制項的調用不是安全執行緒的。該異常是在用普通多線程時會發生。

  

程式碼範例
private void setTextUnsafeBtn_Click(object sender, EventArgs e)
{
this.demoThread = new Thread(new ThreadStart(this.ThreadProcUnsafe));
this.demoThread.Start();
}
//線程不安全的方式
private void ThreadProcUnsafe()
{
this.textBox1.Text = "This text was set unsafely.";
}

 對 Windows 表單控制項進行安全執行緒調用

  1. 查詢控制項的 InvokeRequired 屬性。

  2. 如果 InvokeRequired 返回 true,則使用實際調用控制項的委託來調用 Invoke。

  3. 如果 InvokeRequired 返回 false,則直接調用控制項。

  在下面的程式碼範例中,此邏輯是在一個稱為 SetText 的工具 + 生產力方法中實現的。名為 SetTextDelegate 的委託類型封裝 SetText 方法。TextBox 控制項的 InvokeRequired 返回 true 時,SetText 方法建立 SetTextDelegate 的一個執行個體,並調用表單的 Invoke 方法。這使得 SetText 方法被建立 TextBox 控制項的線程調用,而且在此線程上下文中將直接設定 Text 屬性。

程式碼範例
private void setTextSafeBtn_Click( object sender, EventArgs e)
{
this.demoThread = new Thread(new ThreadStart(this.ThreadProcSafe));
this.demoThread.Start();
}
//安全執行緒的方式
private void ThreadProcSafe()
{
this.SetText("This text was set safely.");
}

 

 

程式碼範例

private void SetText(stringtext)

 

{

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.";
}
相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.