【问题标题】:Why invoke ThreadStart with empty Delegate?为什么用空委托调用 ThreadStart?
【发布时间】:2012-10-05 21:29:44
【问题描述】:

在我必须维护的旧应用程序中进行一些取证考古调查时,我遇到了这个:

这是一个最近转换为 .NET 4.0 的 WPF 应用程序,此代码在后台工作程序中运行

           if(bgWorker1.IsBusy || bgWorker2.IsBusy)
           {
                Thread.Sleep(100); 
                Application.Current.Dispatcher.Invoke(
                    System.Windows.Threading.DispatcherPriority.Background, 
                    new System.Threading.ThreadStart(delegate { })
                );
           }

1 - 通过使用无操作委托调用线程(主 gui)可以实现什么可能的副作用。其他两个线程也在主 gui 线程上执行调用,但只有这个线程将优先级设置为 Normal 以外的其他内容(尽管它们使用 Action 而不是 TreadStart)。

2 - 我遇到的情况奇怪地类似于此应用程序的死锁,并且某些情况告诉我这可能是原因。 (无缘无故地围绕优先级和主 gui 线程)。

谢谢

【问题讨论】:

  • 在我看来毫无意义...
  • 调用可能会阻塞,直到主线程处理完消息。

标签: c# wpf multithreading noop


【解决方案1】:

此线程将导致调用函数阻塞,直到 Dispatcher 的线程可以“处理”(无操作)委托。

这可能不是一个好的做法,应该删除。我怀疑这里的目标是让这个(第三个)BackgroundWorker 的完成事件成为前两个 BackgroundWorkers 何时完成的信号。

一般来说,像这样旋转完成通常是糟糕设计的标志。更好的设计是使用CountdownEvent,这可以由两个BackgroundWorker 实例在完成时发出信号。

然后您可以等待倒计时事件,而不是循环使用 Thread.Sleep 和调度程序调用。

【讨论】:

  • 所以如果我理解正确的话,它基本上会在调度程序的堆栈中设置一个书签并停止线程,直到到达并处理书签。我想这接近于面向副作用的编程的样子:-)。
  • @Newtopian 是的 - 有点。它会一直阻塞,直到 Dispatcher 运行委托(它什么都不做),所以是的,这确实是编程的副作用。
【解决方案2】:
  1. "What possible side-effect would be acheived by [...]" 因为它使用Invoke 而不是BeginInvoke,所以它将是一个阻塞调用。这意味着在您的 noop 委托运行之前,您的后台线程不会继续执行。效果是代码不会继续,直到在执行此 noop 之前排队进入消息循环的所有内容。
  2. "I have cases that strangely resembles deadlock with this application and something tells me that this could be the cause." 对我来说听起来很合理。这段代码既说明了不好的做法,也说明了可能的死锁位置。由于代码引用了其他后台工作人员,可能其他人正在做类似的事情。

现在,似乎很明显 something 是错误的,但如果不了解发生的更多信息,就很难评论如何修复它。我的猜测是,所采用的方法存在一个根本的设计缺陷。

【讨论】:

  • 谢谢,我并不是在寻找一个解决方案,但该代码确实让我不知道它的目的是什么。谢谢。有很大帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-13
  • 1970-01-01
  • 1970-01-01
  • 2016-04-09
相关资源
最近更新 更多