在C#中,Windows Forms(WinForms)控件不是線程安全的,這意味著你不能直接從非UI線程訪問和修改它們
Invoke
或BeginInvoke
方法:Invoke
和BeginInvoke
是Control
類的方法,允許你將一個委托(方法)傳遞給UI線程來執行。Invoke
會等待委托執行完成后返回,而BeginInvoke
則會立即返回,不等待委托執行完成。
示例代碼:
public partial class MyForm : Form
{
public MyForm()
{
InitializeComponent();
}
private void UpdateLabelText(string text)
{
if (label1.InvokeRequired)
{
label1.Invoke((MethodInvoker)delegate { label1.Text = text; });
}
else
{
label1.Text = text;
}
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
// 模擬長時間運行的任務
Thread.Sleep(5000);
string result = "任務完成";
// 更新UI控件
UpdateLabelText(result);
}
}
SynchronizationContext
:SynchronizationContext
是一個抽象類,它提供了一種在不同線程之間同步數據的機制。你可以使用SynchronizationContext.Current
獲取當前線程的上下文,然后在其他線程中使用Post
或Send
方法將委托發送到該上下文。
示例代碼:
public partial class MyForm : Form
{
private SynchronizationContext _syncContext;
public MyForm()
{
InitializeComponent();
_syncContext = SynchronizationContext.Current;
}
private void UpdateLabelText(string text)
{
_syncContext.Post(delegate { label1.Text = text; }, null);
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
// 模擬長時間運行的任務
Thread.Sleep(5000);
string result = "任務完成";
// 更新UI控件
UpdateLabelText(result);
}
}
Task
和async/await
:在.NET Framework 4.5及更高版本中,你可以使用Task
和async/await
關鍵字來簡化多線程編程。當你在異步方法中需要訪問UI控件時,編譯器會自動處理線程同步。
示例代碼:
public partial class MyForm : Form
{
public MyForm()
{
InitializeComponent();
}
private async void button1_Click(object sender, EventArgs e)
{
await Task.Run(() =>
{
// 模擬長時間運行的任務
Thread.Sleep(5000);
return "任務完成";
});
// 更新UI控件
label1.Text = "任務完成";
}
}
請注意,這些示例代碼僅用于演示目的。在實際項目中,你可能需要根據具體需求進行調整。