【发布时间】:2011-10-05 07:39:09
【问题描述】:
我最近一直在开发一个应用程序,我想通过包含在StatusBar 控件中的ToolStripProgressBar 控件在状态栏中显示另一个线程的进度。在我尝试添加此代码之前,我最初的代码更改了 ToolStripStatusLabel 控件的文本,为此我使用了带有委托的 Invoke 方法,一切正常。但是,我发现当我尝试使用ToolStripProgressBar 进行此操作时,对状态栏的Invoke 方法的调用在没有通知的情况下失败(没有错误、没有异常、什么都没有)。从那以后我学到的是,要以这种方式使用进度条,我必须使用BackgroundWorker 控件。所以我的代码有效,但我不明白为什么我不能使用似乎已经有效的Invoke 方法。
一些有效和无效的示例:
成功了
public delegate void changeStatusMessage(String message);
public changeStatusMessage changeStatusMessageDelegate;
public void changeStatusMessageMethod(String message){
if(statusbar.InvokeRequired){
statusbar.Invoke(changeStatusMessageDelegate, new Object[] {message});
}else{
toolstripLabel.Text = message;
}
}
这没用
public delegate void incrementProgressBar(int value);
public incrementProgressBar incrementProgressBarDelegate;
public void incrementProgressBarMethod(int value){
if(statusbar.InvokeRequired){
statusbar.Invoke(incrementProgressBarDelegate, new Object[] {value});
}else{
toolstripProgress.Increment(value);
}
}
在不起作用的示例中,InvokeRequired 属性为 true,因此调用了 Invoke 方法,然后什么也没有发生。正如我预期的那样,这次它会再次调用incrementProgressBarMethod,其中InvokeRequired 为假,从而允许Increment 方法触发。
我真的很想知道为什么这不起作用。正如我所说,我已经改用BackgroundWorker,我只是想要一个解释。
【问题讨论】:
-
TSPB 没有什么特别之处,可以为您提供简单的解释。如果主线程被阻塞,Control.Invoke() 往往很容易死锁,因此“什么都没有发生”并不少见。坚持使用 BackgroundWorker。
-
我从来没有说过我想要一个“简单”的解释,复杂的解释也可以。简单地告诉我 Control.Invoke() 会导致死锁并不足以让我理解原因。提供 Control.Invoke() 是有原因的,为什么我不能将它用于这个控件,当使用相同代码以类似方式处理的控件可以正常工作时。
-
发布演示问题的重现代码,任何人都可以测试,你会得到答案。
标签: c# winforms invoke multithreading invokerequired