概述:本指南詳細解釋了在C#中如何在創建控制項的線程以外的線程中訪問GUI。基礎功能使用`Control.Invoke`(WinForms)或`Dispatcher.Invoke`(WPF),高級功能則利用`SynchronizationContext`實現線程間通信,確保代碼清晰可讀。 在C#中,要 ...
概述:本指南詳細解釋了在C#中如何在創建控制項的線程以外的線程中訪問GUI。基礎功能使用`Control.Invoke`(WinForms)或`Dispatcher.Invoke`(WPF),高級功能則利用`SynchronizationContext`實現線程間通信,確保代碼清晰可讀。
在C#中,要在創建控制項的線程以外的線程訪問控制項,可以使用Control.Invoke(WinForms)或Dispatcher.Invoke(WPF)。以下是詳細的步驟和示例代碼,包括基礎功能和高級功能。
在WinForms中訪問控制項:
基礎功能:
- 創建WinForms應用程式: 創建一個包含按鈕和標簽的WinForms應用程式。
- 使用Invoke訪問控制項: 在另一個線程中使用Control.Invoke訪問控制項。
示例源代碼:
using System;
using System.Threading;
using System.Windows.Forms;
namespace WinFormsThreadedAccess
{
public partial class MainForm : Form
{
public MainForm()
{
InitializeComponent();
}
private void btnAccessControl_Click(object sender, EventArgs e)
{
// 在另一個線程中訪問控制項
Thread thread = new Thread(AccessControl);
thread.Start();
}
private void AccessControl()
{
if (lblStatus.InvokeRequired)
{
// 在UI線程上非同步執行訪問控制項操作
lblStatus.Invoke(new Action(() => lblStatus.Text = "控制項已訪問"));
}
else
{
// 在UI線程上直接訪問控制項
lblStatus.Text = "控制項已訪問";
}
}
}
}
在WPF中訪問控制項:
基礎功能:
- 創建WPF應用程式: 創建一個包含按鈕和標簽的WPF應用程式。
- 使用Dispatcher訪問控制項: 在另一個線程中使用Dispatcher.Invoke訪問控制項。
示例源代碼:
using System;
using System.Threading;
using System.Windows;
namespace WPFThreadedAccess
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void btnAccessControl_Click(object sender, RoutedEventArgs e)
{
// 在另一個線程中訪問控制項
Thread thread = new Thread(AccessControl);
thread.Start();
}
private void AccessControl()
{
if (Dispatcher.CheckAccess())
{
// 在UI線程上直接訪問控制項
lblStatus.Content = "控制項已訪問";
}
else
{
// 在UI線程上非同步執行訪問控制項操作
Dispatcher.Invoke(new Action(() => lblStatus.Content = "控制項已訪問"));
}
}
}
}
高級功能:
在高級功能中,WinForms和WPF均可以使用SynchronizationContext進行線程間通信,代碼更為簡潔。
示例源代碼:
using System;
using System.Threading;
using System.Windows.Forms;
namespace AdvancedThreadedAccess
{
public partial class MainForm : Form
{
private readonly SynchronizationContext synchronizationContext;
public MainForm()
{
InitializeComponent();
// 獲取當前同步上下文
synchronizationContext = SynchronizationContext.Current;
}
private void btnAccessControl_Click(object sender, EventArgs e)
{
// 在另一個線程中訪問控制項
Thread thread = new Thread(AccessControl);
thread.Start();
}
private void AccessControl()
{
// 在UI線程上非同步執行訪問控制項操作
synchronizationContext.Post(new SendOrPostCallback(UpdateLabel), "控制項已訪問");
}
private void UpdateLabel(object state)
{
// 在UI線程上更新標簽文本
lblStatus.Text = state.ToString();
}
}
}
在WPF中,Dispatcher本身就是一種同步上下文,所以高級功能的WPF示例代碼與基礎功能示例代碼相似。