【问题标题】:Is it unsafe to use local variables in a call to begininvoke在调用 begininvoke 时使用局部变量是否不安全
【发布时间】:2017-10-16 13:01:24
【问题描述】:

我必须从我的同事那里接管一个用 C# 编写的更大应用程序的源代码。它使用 windows 形成一个线程,现在它可以正常工作。 但我不确定的一件事是,他处理从线程提升到应用程序中的 windows 窗体的委托中使用的参数的方式。我不知道为什么,但他定义了许多具有不同数量元素的不同对象数组,例如:

private object[] delegateArray1;
private object[] delegateArray3;
private object[] delegateArray3A;

然后在他使用的代码中

delegateArray1 = new object[1]; // in the constructor of the thread class 
delegateArray3 = new object[3]; 
delegateArray3a = new object[3];

// and this somewhere in the thread loop
delegateArray3[0] = systemtests.FehlerText;
delegateArray3A[1] = CheckState.Unchecked;
delegateArray3A[2] = testKanal;
sender.BeginInvoke(merkerInfoDelegate, delegateArray3);

其中sender 是创建线程的容器控件。 merkerInfoDelegate 指向带有签名的方法

public void InfoAnzeige(string scrollText, CheckState state, int kanal);

我的第一个问题:

我传递给 BeginInvoke 方法的变量/对象是否可能被垃圾收集,因此在委托方法最终执行时无效。如果是,我该如何防止这种情况发生?

不能这样调用委托吗:

sender.BeginInvoke(merkerInfoDelegate, systemtests.FehlerText, CheckState.Unchecked, testKanal);

我想让代码更易读、更安全、更可靠。我想声明类 MouseEventArgs 之类的类,它由这些参数组成,并且封装了要传递给 windows 窗体类中的委托方法的所有必要数据...

public InfoDelegateEventArgs
{
    public String Fehlertext;
    public CheckState state;
    public int Kanal;
}

可以这样使用:

idea = new InfoDelegateEventArgs(){...};
sender.BeginInvoke(merkerInfoDelegate, idea);

【问题讨论】:

  • 是否有特定的理由通过 CheckState 而不仅仅是一个布尔值?
  • 你的变量没有被垃圾回收——当你调用BeginInvoke时,它们仍然被引用。
  • 您可以使用sender.BeginInvoke(new Action(() => InfoAnzeige(systemtests.FehlerText, CheckState.Unchecked, testKanal)) 来避免所有这些混乱。
  • @Botonomous:我不这么认为,但参数的数量和类型仅用于解释:-)
  • @xxbbcc:在调用BeginInvoke 时,希望它们仍然被引用。但它们是在几小时或几天后执行目标方法的时候吗?我的意思是,如果我离开调用BeginInvoke 的方法,堆栈上的局部变量将会丢失......

标签: c# multithreading delegates


【解决方案1】:

传递“局部”变量是安全的,但请记住,一旦传递它们,它们就不再是“局部”的了。引用现在已传递给另一个可能在单独线程上同时运行的操作。现在多个线程可以访问“本地”变量,因此可能需要锁定或其他线程安全处理。

您不必担心它会被 GC,因为仍然有一个引用被传递给 BeginInvoke

【讨论】:

  • 值类型变量我觉得没问题,但是引用类型值呢?
  • @WolfgangRoth 是的,OP 正在传递数组,它们是引用。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-12-30
  • 2016-07-26
  • 2020-06-22
  • 1970-01-01
  • 1970-01-01
  • 2016-07-14
  • 1970-01-01
相关资源
最近更新 更多