[英]WinForms interthread modification
每當我想從另一個線程修改winform時,我需要使用
->Invoke(delegate, params)
以便修改發生在winform自己的線程中。
對於需要修改gui的每個函數,我需要另一個委托函數。
是否有一些方案允許我限制所需的委托功能的數量? 我有一個控制器類,可以在一個地方處理整個gui,我考慮過重用代表但是聞起來很糟糕。
我認為我的問題可以適用於winform可以運行的所有語言
如果您使用的是C#3,則可以使用lambda,而在C#2中,則使用匿名委托。 當不需要重用行為時,這些簡化了語法。 我經常做的一件事是在表單代碼中進行同步,而不是在控制器中進行。 控制器不應該受到這種技術更具體的“管道”問題的困擾,而不是控制器邏輯。
public void ResetFields()
{
// use "delegate" instead of "() =>" if .Net version < 3.5
InvokeOnFormThread(() =>
{
firstInput.Text = Defaults.FirstInput;
secondInput.Text = Defaults.SecondInput;
thirdChoice.SelectedIndex = Defaults.ThirdChoice;
});
}
// change Action to MethodInvoker for .Net versions less than 3.5
private void InvokeOnFormThread(Action behavior)
{
if (IsHandleCreated && InvokeRequired)
{
Invoke(behavior);
}
else
{
behavior();
}
}
作為一種做法,使表單中的所有公共方法調用“InvokeOnFormThread”。 或者,您可以使用AOP攔截表單上的公共方法調用並調用“InvokeOnFormThread”,但上面已經運行得很好(如果您保持一致並記住總是在窗體或UserControls上的公共方法上執行)。
看看使用現有的System.Action<T>
和System.Func<T,T>
委托:
control.Invoke(
new Action<int, string>(
(i, s) => MessageBox.Show(String.Format(s, i))), 1, "{0}");
int iret = (int) control.Invoke(new Func<int, int>(i1 => i1 + 1));
Michael Meadows的答案是如何集中更新GUI表單邏輯的一個很好的例子。
關於調用眾多代表來同步前端的性能(我們很容易被痴迷),不久之前,我編寫的軟件在GUI同步方面優於同等的C ++(本機)Windows應用程序! 這完全歸功於BeginInvoke
和ThreadPool
類。
使用Action<>
和Func<>
委托和ThreadPool
類也是有益的,並考慮一般的Invoke
模式(由上面的Michael公開):
public void TheGuiInvokeMethod(Control source, string text)
{
if (InvokeRequired)
Invoke(new Action<Control, string>(TheGuiInvokeMethod, source, text);
else
{
// it is safe to update the GUI using the control
control.Text = text;
}
}
其中TheGuiInvokeMethod
確實位於表單或其他控件中。
我記得關閉檢查並手動驗證我使用的每個電話都是安全的。
由於我保證了某些線程的位置(信號量),或者因為它們調用了可以在其他進程上使用的底層API函數,因此可以將其中令人驚訝的數量稱為交叉線程。
我最終仍然有很多調用,通常是在上下文對象上,所以我可以使用MethodInvoker。
我還在Control.Invoke中遇到了一個令人討厭的錯誤,驅使我寫一個自定義調用程序庫。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.