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が false であるため、Incrementメソッドを起動できるように再度呼び出すと予想していました。

なぜこれがうまくいかないのか本当に知りたいです。私が言ったように、私はすでに を使用するように改造しましたBackgroundWorker。説明が欲しいだけです。

4

1 に答える 1

0

postmessage API の呼び出しを呼び出し、Windows メッセージでメッセージをエンキューします。UI スレッドがブロックされている場合、キューに入れられたメッセージをプッシュできないため、デッドロックが発生する可能性があり、何も起こりません。必要な呼び出しの反対側は起動されず、何かがそれを待っている場合は、バン、デッドロックします。

これが、Invoke に注意する必要がある理由です。

.NETの親スレッドで関数を呼び出す方法は?

しかし、あなたの問題はデリゲートの作成にあります。それはnullデリゲートです。invokeによって呼び出されているのと同じスレッドでデリゲートを作成する必要があります. )。

    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 Framework 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 に答える