21

我是一个新手程序员,所以我在这里可能完全误会了,但是这个问题让我感到不安。

这实际上是这个问题的后续行动。

公认的答案是,您必须调用 InvokeRequired 以避免一些开销,因为您有可能已经在 UI 线程上进行操作。

从理论上讲,我同意它可以节省一些时间。经过一些测试,我发现使用 Invoke 所花费的时间大约是正常调用操作的两倍(测试比如设置标签的文本 n 次,或者在 RichTextBox 中放置一个非常非常大的字符串)。

但!然后是练习。

MSDN 文档说:

此属性可用于确定是否必须调用调用方法,如果您不知道哪个线程拥有控件,这可能很有用。

在大多数情况下,您确实知道何时尝试从另一个线程访问控件。实际上,我能想到的唯一情况是,当从可以由线程 X 以及所有者线程调用的方法访问控件时。这对我来说是一个非常不可能的情况。

即使您真的不知道哪个线程试图操纵控件,也有一个事实是 UI 线程不必那么频繁地更新。25-30 fps 之间的任何内容都适合您的 GUI。并且在 UI 控件中所做的大多数更改都需要不到几毫秒的时间来执行。

因此,如果我理解正确,您必须检查是否需要调用的唯一情况是当您不知道哪个线程正在访问控件并且 GUI 更新需要超过 40 毫秒才能完成时。

然后是我在http://programmers.stackexchange.com上提出的这个问题的答案。这表明您不应该在不需要时忙于过早的优化。特别是如果它牺牲了代码的可读性。

所以这给我带来了我的问题:当你知道不同的线程访问控件时,你不应该只使用调用吗,并且只有当你知道你的 UI 线程可以访问那段代码并且你发现它应该运行得更快时,你应该检查是否需要调用?

PS:在校对我的问题后,听起来我真的在咆哮。但实际上我只是好奇为什么 InvokeRequired 似乎被许多比我更有经验的程序员过度使用。

4

2 回答 2

9

你在这里断章取意。您链接的第一个问题链接了另一个问题,该问题专门关于编写线程安全方法来访问 UI 控件。

如果您不需要对 UI 控件的线程安全访问,因为您知道不会从另一个线程更新它,那么当然,您不应该使用这种技术。只需更新您的 UI 控件,而无需使用InvokeRequiredor Invoke

另一方面,如果调用总是源自 UI 线程以外的线程,则只需使用Invoke而不首先检查InvokeRequired.

这导致了三个简单的规则:

  1. 如果仅从 UI 线程更新控件,则既不使用InvokeRequired也不使用Invoke
  2. 如果仅从 UI 线程以外的线程更新控件,请仅使用Invoke.
  3. 如果从 UI 线程和其他线程更新控件,请InvokeInvokeRequired.
于 2013-07-02T09:21:34.060 回答
8

在实践中,人们倾向于从外部线程和拥有线程调用相同的方法。通常的模式是方法本身确定线程是否是拥有线程。如果是,则执行后续代码。如果不是,则该方法使用Invoke此时间调用自己的自身。

这样做的一个好处是它使代码更紧凑,因为您有一个与操作相关的方法而不是两个。

另一个可能更重要的好处是它减少了引发跨线程异常的机会。如果这两种方法在任何时候都可用,并且两个线程都可以选择两者中的任何一种,那么看似合法的方法调用就有可能引发异常。另一方面,如果只有一种方法可以适应这种情况,它会提供更安全的接口

于 2013-07-02T09:19:34.020 回答