winform非UI執行緒操作UI控制元件方式
阿新 • • 發佈:2021-02-08
序言
初學者遇到在非UI執行緒中操作控制元件會異常,這時會很蒙圈,包括我初學winform的時候也是一樣的,閒下來沒事的時候對該操作做了一個demo嘗試,接下來做一個解釋與記錄。
解決方案
直接附上程式碼:
using System;
using System.Threading;
using System.Windows.Forms;
namespace WindowsFormsApp1
{
public partial class Form1 : Form
{
delegate void SetLabel(string text);
private void ChangeLabel4Text(string text)
{
label4.Text = text;
}
WindowsFormsSynchronizationContext context;
SynchronizationContext context1;
public Form1()
{
InitializeComponent();
context = SynchronizationContext. Current as WindowsFormsSynchronizationContext;
context1 = SynchronizationContext.Current;
System.Threading.Timer timerWindows = new System.Threading.Timer(TimerCallbackWindows, context, TimeSpan.FromSeconds(0), TimeSpan.FromSeconds(1));
System.Threading.Timer timerBase = new System.Threading.Timer(TimerCallbackBase, context1, TimeSpan.FromSeconds(0), TimeSpan.FromSeconds(1));
}
private void TimerCallbackWindows(object state)
{
// 不是從UI執行緒改變控制元件會異常的
//label3.Text = Guid.NewGuid().ToString();
context.Post(s => label1.Text = Guid.NewGuid().ToString() + "-WindowsFormsSynchronizationContext", state);
Invoke(new MethodInvoker(() =>
{
label3.Text = Guid.NewGuid().ToString() + "-MethodInvoker";
}));
}
private void TimerCallbackBase(object state)
{
context1.Post(s => label2.Text = Guid.NewGuid().ToString() + "-SynchronizationContext", state);
// 使用系統自帶MethodInvoker委託
Invoke(new MethodInvoker(() =>
{
label4.Text = Guid.NewGuid().ToString() + "-MethodInvoker";
}));
Thread.Sleep(TimeSpan.FromMilliseconds(500));
// 自定義委託
Invoke(new SetLabel(ChangeLabel4Text), Guid.NewGuid().ToString() + "-Invoke");
// 採用Action方式
Invoke(new Action(() =>
{
// TODO:操作UI控制元件
}));
}
}
}
效果如下:
主流方式比較推薦使用
Action