1

for ループを含むメソッドがあります。for ループでは、メインフォームのラベルのテキストを更新したいのですが、変更はループの終了後にのみ行われます。

私はこのような別のスレッドでそれをやろうとしました:

Thread firstthread = new Thread(new ThreadStart(myMethod));
firstthread.Start();

私がそれをしたときInvalidOperationException、別のスレッドなどのコントロールにアクセスしようとしたためにエラーが発生しました。

ループの進行中にループからメインフォームのラベル (または他のコントロール) を更新するにはどうすればよいですか?

4

3 に答える 3

4

を使用する必要がありますBackgroundWorker。実行時間の長いループをDoWorkイベント ハンドラー内に配置します。バックグラウンド スレッドで実行され、UI スレッドをブロックしません。true に設定ReportProgressし、それにイベント ハンドラーをアタッチして、ラベル (またはその他のもの) を定期的に更新できるようにすることができます。ProgressReported イベントは UI スレッドで実行されます。UI スレッドでも実行される Completed イベントにハンドラーを追加することもできます。

詳細とコード サンプルについては、BackgroundWorkerのMSDN ページを参照してください。

于 2012-10-08T13:47:44.463 に答える
1

Servy が言ったように、次の簡単な例のようなものを使用できます。

public partial class Form1 : Form
{
    BackgroundWorker bgw;
    public Form1()
    {
        InitializeComponent();
        bgw = new BackgroundWorker();
        bgw.DoWork += new DoWorkEventHandler(bgw_DoWork);
        bgw.ProgressChanged += new ProgressChangedEventHandler(bgw_ProgressChanged);
        bgw.WorkerReportsProgress = true;
    }

    void bgw_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        string text = (string)e.UserState;
        SetValue(text);//or do whatever you want with the received data
    }
    void SetValue(string text)
    {
        this.label1.Text = text;
    }

    void bgw_DoWork(object sender, DoWorkEventArgs e)
    {
        for (int i = 0; i < 10000; i++)
        {
            string text = "Value is " + i.ToString();
            bgw.ReportProgress(1, text);
            Thread.Sleep(1000);
        }
    }

    private void button1_Click(object sender, EventArgs e)
    {
        bgw.RunWorkerAsync();
    }

}

于 2012-10-08T14:19:58.300 に答える
1

Form (Windows.Forms の場合) またはウィンドウの Dispatcher オブジェクト (WPF の場合) で Invoke メソッドと BeginInvoke メソッドを確認する必要があります。

例えば:

this.BeginInvoke(new Action(() => this.Text = "ciao"));

フォームのタイトル バーを変更します。

BeginInvoke は非同期です。変更が発生するのを待ちません。一方、Invoke は同期であり、変更が完了するまでブロックします。特にその必要がない限り、偶発的なデッドロックの可能性を減らす BeginInvoke を使用することをお勧めします。

これにより、並行スレッドから UI を更新できるようになり、使用しているスレッド メカニズム (TPL タスク、プレーン スレッドなど) に関係なく機能します。

于 2012-10-08T13:44:50.240 に答える