类型安全Control.Invoke C# [英] type-safe Control.Invoke C#
问题描述
我正在使用C#编写一个包含2个线程的软件
I am programming a software in C# at work that contains 2 Threads
- 控制窗体(Windows窗体)并与用户连接的线程.
- 一个在后台检查在线数据的线程.
当在线数据不规则时,我需要第二个线程在表格上打印消息.
I need the second thread to print a massage on the form when the online data is irregular.
因为只有创建控件的线程才能更改它,所以我正在使用委托. 第二个线程通过Control.Invoke方法调用第一个线程来执行委托.
because only the thread that created the control can change it, I am using delegates. the second thread calls the first thread to execute a delegate by the Control.Invoke method.
示例:
public partial class Form1 : Form
{
public delegate void SafeCallDelegate(string text);
public static SafeCallDelegate d;
public Form1()
{
InitializeComponent();
d = new SafeCallDelegate(addText);
}
private static void addText(string text)
{
richTextBox1.Text += text + "\n";
}
}
static class Program
{
static Thread secondThread;
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
secondThread = new Thread(SecondThreadFunc);
secondThread.Start();
Application.Run(new Form1());
}
static void SecondThreadFunc()
{
int counter = 0;
do
{
if (Form.ActiveForm == null) continue;
Form.ActiveForm.Invoke(Form1.d, new object[] { "SecondThreadFunc counter: " + counter.ToString() });
counter++;
Thread.Sleep(1000);
} while (true);
}
}
我可以接受这种不太干净的解决方案,但是我的问题是这根本不是类型安全的.
I can live with this not very clean solution, but my problem is that this is not type-safe at all.
Control.Invoke函数接受一个对象数组,无论委托要求什么,这都可能导致运行时异常.
the Control.Invoke function takes an array of objects, regardless of what the delegate requires and this can result in a run-time exception.
有没有一种类型更安全并且可以解决我的问题的方法?
Is there a method to use that is more type-safe and can solve my problem?
谢谢.
推荐答案
Instead of passing the arguments to Invoke
, pass them as a closured variable within the delegate.
所以,代替这个:
Form.ActiveForm.Invoke(Form1.d, new object[] { "SecondThreadFunc counter: " + counter.ToString() });
写这个:
Form.ActiveForm.Invoke
(
new Action
(
() => Form1.d("SecondThreadFunc counter: " + counter.ToString())
)
);
这避免了将参数传递给Invoke
的问题,并消除了类型安全性问题.
This avoids the problem of passing arguments to Invoke
and eliminates the type-safety issue.
如果您觉得这有些罗y,还可以定义一个简单的辅助程序扩展方法:
If that seems a little wordy to you, you can also define a simple helper extension method:
static class Helpers
{
static public void MyInvoke(this Control control, Action action)
{
if (control.InvokeRequired)
{
control.Invoke(action);
}
else
{
action();
}
}
}
现在您所要写的主要形式是:
Now all you have to write in your main form is this:
this.MyInvoke( () => addText("SecondThreadFunc counter: " + counter.ToString()));
现在,您可以摆脱所有SafeCallDelegate的内容,只在需要时传递所需的任何lambda.
You can now get rid of all that SafeCallDelegate stuff and just pass whatever lambda you want when you need it.
这篇关于类型安全Control.Invoke C#的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!