0

我最近一直在开发一个应用程序,我想通过ToolStripProgressBar控件中包含的StatusBar控件在状态栏中显示另一个线程的进度。在我尝试添加此代码之前,我最初拥有更改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这次它会再次调用 whereInvokeRequired是错误的,从而允许Increment触发该方法。

我真的很想知道为什么这不起作用。正如我所说,我已经重新调整以使用 a BackgroundWorker,我只是想要一个解释。

4

1 回答 1

0

Invoke 调用 postmessage API 并在 windows 消息上排队消息。如果 UI 线程被阻塞,那么你可能会出现死锁,因为它无法推送排队的消息,所以什么都不会发生。调用 required 的另一端没有被触发,如果有东西在等待它,砰,死锁。

这就是您需要小心使用 Invoke 的原因。

如何在.NET 中调用父线程上的函数?

但是您的问题在于委托的创建,它是一个空委托,您需要在调用调用它的同一线程上创建委托,因为其他方式,底层系统将无法编组委托(它是一个指针)。

    private void changeStatusMessageMethod(String message)
    {
        if (this.InvokeRequired)
        {
            var changeStatusMessageDelegate = new changeStatusMessage(changeStatusMessageMethod);
            this.Invoke(changeStatusMessageDelegate, new Object[] { message });
        }
        else
        {
            toolstripLabel.Text = message;
        }
    }
    delegate void incrementProgressBar(int value);
    private void incrementProgressBarMethod(int value)
    {
        if (this.InvokeRequired)
        {
            var incrementProgressBarDelegate = new incrementProgressBar(incrementProgressBarMethod);
            this.Invoke(incrementProgressBarDelegate, new Object[] { value });
        }
        else
        {
            toolstripProgress.Increment(value);
        }
    }

这适用于 dotnet 框架 v4

    private void button1_Click(object sender, EventArgs e)
    {
        var t = new System.Threading.Thread(new System.Threading.ThreadStart(x));
        t.Start();
    }

    private void x()
    {
        do
        {
            changeStatusMessageMethod(DateTime.Now.ToString());
            System.Threading.Thread.Sleep(1000);
        } while (true);
    }

    private void button2_Click(object sender, EventArgs e)
    {
        var t = new System.Threading.Thread(new System.Threading.ThreadStart(y));
        t.Start();
    }

    private void y()
    {
        do
        {
            incrementProgressBarMethod(1);
            System.Threading.Thread.Sleep(1000);
        } while (true);
    }
于 2013-07-01T19:14:39.923 回答