我想调用一个操作UI线程控件的方法。我的代码有效,我想优化。我指的是resource on MSDN。
根据那里,我们应该做
public delegate void myDelegate(int anInteger, string aString);
//...
Label1.Invoke(new myDelegate(myMethod), new Object[] {1, "This is the string"});
每次调用会引入一个孤立的委托对象(内存泄漏)吗?
当我使用下面的委托的静态实例执行此操作时,然后在每次调用时使用此实例来调用:
private static _delegateInstance = new myDelegate(myMethod);
//...
Label1.Invoke(_delegateInstance , new Object[] {1, "This is the string"});
这是线程安全吗?我认为这会有更好的性能,因为委托实例只创建一次吗?
答案 0 :(得分:2)
上面的两个答案给出了一些见解。如果您想获得更深入的信息,那么有一篇好文章here。
两种方法都是线程安全的,因为在调用时,线程池为每次调用分配一个线程。锁定的可能性很大,但是如果你阅读那篇文章,可以解决这个问题。
此外,您需要记住.Net处理UI线程的方式略有不同。如果您正在处理WPF,则必须考虑调度员。请参阅here。
最终,我不确定你会用第二段代码获得大幅度的性能提升,所以我倾向于坚持使用第一段代码。
<磷>氮答案 1 :(得分:2)
另一种“模式”(如果可以调用它)是让方法只调用自己,假设它是Form
类的一部分:
void myMethod(int anInteger, string aString)
{
if (InvokeRequired)
{
Invoke(new Action<int,string>(myMethod),anInteger,aString);
return;
}
Label1.Text = aString;
}
Action
对象将保留在堆上,更改文本属性,然后在下次扫描时进行GC。除非该方法保留一些外部资源,例如IE的句柄,文件等,否则我无法看到它受到性能影响。
答案 2 :(得分:1)
这会在每次调用时引入一个孤立的委托对象(内存泄漏)吗?
不,不会,没关系。
但是为了避免每次使用existing时都创建一个委托(如果你的方法需要2个字符串参数而没有返回):
Label1.Invoke.Invoke((Action<string, string>)myMethod,
new object[] { 1, "This is the string" });
答案 3 :(得分:0)
首先,C#是一种托管语言,因此没有内存泄漏。如初。
其次,当您尝试优化时,不要将MSDN作为最终裁定。您在那里找到的许多代码片段甚至都不符合MS自己的编码标准(即使是最基本的编码标准)甚至是常识。
第三,行:private _delegateInstance = new myDelegate(myMetho);不会创造任何静态的东西。它创建一个变量,用于保存从新myDelegate(myMethod)返回的新实例。
最后,使用“new”关键字肯定会在每次调用中创建新的myDelegate对象,以及与您编写的第二个代码段完全不同的行为,但在某些情况下,这是必需的。
您可能想要使用您编写的第二个选项,但真正的事实是您应该花时间阅读\了解更多关于委托和C#的内容。
祝你好运,享受。答案 4 :(得分:0)
您的第一个代码段每次都会创建一个委托对象实例。这不会导致任何泄漏,但会增加需要进行垃圾回收的对象数量。
您的第二个代码段每次都不会创建委托对象,但是不可能(假设myMethod是一个实例方法),因为静态成员不能使用实例成员。
Darin Dimitrov错了 - 他的代码使用现有的Action代理而不是自定义代理,但它每次都会创建一个Action委托对象(与第二个代码段不同)。 因此,您可以使用以下代码:
private Action<int, string> _delegateInstance = myMethod;
//...
Label1.Invoke(_delegateInstance , new Object[] {1, "This is the string"});