为什么我们需要在线程安全的调用块中直接调用?

时间:2012-05-21 03:19:51

标签: c# .net thread-safety

请参阅MSDN处的线程安全呼叫教程,查看以下语句:

// InvokeRequired required compares the thread ID of the
// calling thread to the thread ID of the creating thread.
// If these threads are different, it returns true.
if (this.textBox1.InvokeRequired) { 
    SetTextCallback d = new SetTextCallback(SetText);
    this.Invoke(d, new object[] { text });
} else {
    this.textBox1.Text = text;
}

当然,我已经在我的代码中多次使用它了,并且理解为什么要使用它。 但是我仍然对这些陈述有一些不明确的问题,所以请任何人帮我找到它们。

问题是:

  1. 代码是否可以仅使用if主体中的语句正确运行?我试过,如果控件没有完全初始化,它似乎只是导致问题。我不知道还有更多问题吗?
  2. 通过调用者直接调用方法(else body)实例的优势是什么?它是节省资源(CPU,RAM)还是什么?
  3. 谢谢!

2 个答案:

答案 0 :(得分:2)

你当然可以使用Invoker来打电话,但是:

  • 它通常会使代码更加冗长和难以阅读。
  • 效率较低,因为有几个额外的层可以与之竞争(设置委托,调用调度程序等)。

如果您确定自己总是在GUI线程上,则可以忽略上述检查并直接致电。

答案 1 :(得分:1)

  1. 如果你总是只运行if语句的第一部分,它总是没问题,因为Invoke已经检查你是否在UI线程上。
    1. 你不想这样做的原因是Invoke必须做很多工作来运行你的方法,即使你已经在正确的线程上。这是它必须做的事情(从Control.cs的源代码中提取):
      • 通过向上遍历父控制链找到编组控件
      • 检查控件是否为ActiveX控件,如果是,请求非托管代码权限
      • 确定是否需要异步调用调用以避免潜在的死锁
      • 获取调用线程的执行上下文的副本,以便在最终调用委托时使用相同的安全权限
      • 排队方法调用,然后发布消息以调用方法,然后等待(如果是同步的)直到完成
  2. 在UI线程直接调用期间,第二个分支中的所有步骤都不需要,因为所有前提条件都已经得到保证,所以它肯定会更快,尽管公平,除非你非常更新控件经常,你不太可能注意到任何差异。