當使用子執行緒(Other Thread)更新主執行緒所顯示的UI元件時,通常會遇到「跨執行緒作業無效: 存取控制項 ... 時所使用的執行緒與建立控制項的執行緒不同」這個錯誤,可以利用UI.InvokeRequired來進行判斷跨執行緒的問題與導正回主執行緒。
當函數是沒有參數時,可以不用自建委派,直接利用C#提供的MethodInvoker即可:
private void NoneParameterFunction()
{
if (UI.InvokeRequired)
{
MethodInvoker TA = new MethodInvoker(NoneParameterFunction);
this.Invoke(TA, new object[]{});
}
else
{
// Do something...
}
}
當函數是有參數時,需要自建委派,利用該委派來回呼方法,以達到導正執行緒的目的:
1. 先建立委派
private void delegate WithParameterFunctionHandler(string sParam);
2. 在方法中使用委派
private void WithParameterFunction(string sParam)
{
if (UI.InvokeRequired)
{
WithParameterFunctionHandler TA = new WithParameterFunctionHandler(WithParameterFunction);
this.Invoke(TA, new object[] {sParam});
}
else
{
// Do something...
}
}
另可以參考Shin.Li的文章,將InvokeRequired寫成static class方便使用,也是一個亮點用法。
未免參考網頁消失,節錄內容如下,原文詳見:https://dotblogs.com.tw/shinli/2015/04/16/151076
為了更有效便利的使用Invoke跟InvokeRequired去執行跨執行緒控制項操作,我通常會把這個方法撰寫class的擴充方法,並且加入MethodInvoker 委派/lambda的應用。
public class main
{
//參考用controls
TextBox tb = new TextBox();
void Func()
{
//使用lambda
tb.InvokeIfRequired(() =>
{
tb.Text = "hello";
});
//使用Action
tb.InvokeIfRequired(helloAction);
}
void helloAction()
{
tb.Text = "hello";
}
}
//擴充方法
public static class Extension
{
//非同步委派更新UI
public static void InvokeIfRequired(this Control control, MethodInvoker action)
{
if (control.InvokeRequired)//在非當前執行緒內 使用委派
{
control.Invoke(action);
}
else
{
action();
}
}
}
請先 登入 以發表留言。