1

スレッドの実行は、メイン アプリケーションからかなり分離されていることがわかりました。変数 (クラスでグローバルに宣言されている) を変更することはできず、スレッド内で新しい値を与えるだけでは、フォーム プロパティなどを変更することはできません。

スレッドが実行されると、スレッド内からラベルのテキストを変更するにはどうすればよいでしょうか?

メインプログラムで使用されていないため、値をロックする必要はないと思うので、デッドロックは発生しません。

私が試したこと、それは失敗しました。

グローバル変数を持つ (int = 0)

テスト スレッドを実行して、変数を 5 に変更します。

その番号をスレッドの外に表示したい場合(messagebox.show(int.tostring())) var はまだ 0 です

スレッド内からメイン フォームの内容を変更するにはどうすればよいでしょうか。

コード

私が使用しなかったスレッドを作成するこのコードはこれでした。

        Thread threadA = new Thread(new ThreadStart(DoWork));
        threadA.Start();

その方法を使用すると、エラーが発生します

「クロススレッド操作が無効です: コントロール 'button1' は、それが作成されたスレッド以外のスレッドからアクセスされました」

スレッドで何かを編集または変更しようとしたとき。

だから私はこのコードを使用しました。

lbldirectory は、部分クラスの名前です。

            // StartFileCheckProcess();
            workerObject = new lbldirectory(); 
            workerThread = new Thread(workerObject.DoWork);

            // the worker thread.
            workerThread.Start();

DoWork は、フォームのプロパティを変更しようとするクラスです。

これは DoWork クラスです。それは本当に単純なクラスですが、なぜこれが起こるのかを理解するだけであり、他の人はその理由とこれを克服する方法を理解するだけです.

public void DoWork()
        {
            button1.Text = "Hello there";
        }

これでスレッドが実行され、スレッドが機能します。フォームの何も変更できません。

修正された回答 (Tudor と Konstantin Vasilcov 提供)

ボタンクリックイベント。

var t = new Thread(TEST);
    t.Start();

スレッドが開始するクラス

private void TEST()
            {
                for (int i = 0; i < 10; i++)
                {
                    lbl_CurrentFile.BeginInvoke(
                    ((Action)(() => lbl_CurrentFile.Text = i.ToString())));
                    Thread.Sleep(1000);
                }
            }

スレッド内のラベルのテキストを正常に変更します

4

2 に答える 2

7

ここで注意すべきことが 2 つあります。

1. GUI コントロールの変更: GUI スレッドのみがコントロールを変更する必要があります。Invoke他のスレッドは、更新を/経由で GUI スレッドに転送する必要がありますBeginInvoke

 var t = new Thread(
    o => 
    {
         textBox.BeginInvoke(
             ((Action)(() => textBox.Text = "text")));
    });

2.スカラー値または参照の変更: 通常、これは問題なく実行できますが、データの競合には注意してください。

于 2012-10-03T07:35:56.307 に答える
6

バックグラウンド スレッドから GUI にアクセスする必要がある場合は、Control.Invokeメソッドを使用する必要があります。

public void DoWork()
{
    button1.Invoke(new Action(() =>
    {
        button1.Text = "Hello there";
    }));            
}

複数のスレッド間でいくつかの変数を共有している場合、共有変数がスレッドの 1 つによってアクセスされるたびに、同期化手法の 1 つによって明示的に保護する必要があります。そこには必要な情報がたくさんあると思います:スレッドの同期 (C# プログラミング ガイド)

于 2012-10-03T07:33:23.083 に答える