为什么要使用空委托调用ThreadStart?

3
在我维护的一些旧应用程序中进行法医考古调查时,我发现了这个问题:
这是一个WPF应用程序,最近已转换为.NET 4.0,并且这段代码在后台工作者内运行。
           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线程上执行委托调用,但只有这个线程将优先级设置为与正常情况不同的值(它们使用Action而不是TreadStart)。

2- 我遇到了一些类似于死锁的情况,并且我感觉这可能是原因之一(在没有明显原因的情况下调整优先级和主GUI线程)。

谢谢


在我看来毫无意义。 - japreiss
那个调用可能会阻塞,直到主线程处理完消息。 - CodesInChaos
2个回答

5

这个线程会使调用函数阻塞,直到Dispatcher的线程可以“处理”(没有操作)委托。

这通常不是一个好的做法,应该被删除。我猜测这里的目标是允许这个(第三个)BackgroundWorker的完成事件成为前两个BackgroundWorker完成时的信号。

一般来说,像这样等待完成常常意味着设计有缺陷。一个更好的设计是使用CountdownEvent,由两个BackgroundWorker完成时发出信号。

然后你只需要等待倒计时事件而不是循环使用Thread.Sleep和派发器调用。


所以如果我理解正确的话,它基本上在调度程序的堆栈中设置了一种书签,并且暂停线程直到达到并处理该书签。我猜这差不多就是副作用导向编程的样子 :-)。 - Newtopian
@Newtopian 是的 - 有点像。它会阻塞直到 Dispatcher 运行委托(什么也不做),所以是的,这确实是通过副作用编程。 - Reed Copsey

2
  1. "通过 [...]" 因为它使用的是 Invoke 而不是 BeginInvoke,所以这将是一个阻塞式调用。这意味着你的后台线程在 noop 委托运行之前不会继续执行。影响是代码直到在此 noop 之前排队到消息循环中的所有内容都被执行完毕后才会继续执行。
  2. "我有一些情况非常类似于应用程序死锁,有些东西告诉我这可能是原因。" 听起来很有道理。这段代码既是糟糕的做法,也可能导致死锁。由于代码引用了其他后台工作器,可能是其他人在做类似的事情。

现在,似乎很明显有“问题”,但是如果不知道更多详细信息,就很难评论如何修复它。我猜测,采取的方法存在基本的设计缺陷。


谢谢,我并不是在寻找一个解决方案,但那段代码确实让我很困惑它的目的是什么。非常感谢,帮了我很多。 - Newtopian

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接