0

私はここで何が間違っているのですか?

私の計画は、「クロススレッド操作が無効です」という例外を取得せずに、別のスレッドからラベルテキストプロパティを変更することです。

    private void button1_Click(object sender, EventArgs e)
    {
        Thread thread1 = new Thread(new ThreadStart(ChangeTime));
        thread1.Start();
    }

    delegate void SetTimeDelegate();

    private void ChangeTime()
    {
        while (true)
        {
            if (lbl1.InvokeRequired)
            {
                SetTimeDelegate setTime = new SetTimeDelegate(ChangeTime);
                lbl1.Invoke(setTime);


            }
            else
            {
                lbl1.Text = DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss tt");
                Thread.Sleep(1000);
            }
        }
    }
4

1 に答える 1

3

BeginInvoke別のスレッドから UI コントロールを更新するには、またはInvokeメソッドを呼び出す必要があります。特定のコントロールのメソッドまたはフォームのメソッドを使用できます。

元のコードには無限再帰があります。デリゲートが同じメソッドを呼び出していることを除いて、正しく呼び出しています。時間でラベルを更新するための別のメソッドを作成し、デリゲートにその新しいメソッドを呼び出します。

private bool _IsShuttingDown = false;

private void ChangeTime()
{
   while (!_IsShuttingDown)
   {
      if (lbl1.InvokeRequired)
      {
         SetTimeDelegate setTime = new SetTimeDelegate(UpdateTimeLabel);
         lbl1.Invoke(setTime);
         Thread.Sleep(1000);
      }
      else
      {
         UpdateTimeLabel();
         Thread.Sleep(1000);
      }
   }
}

private void UpdateTimeLabel()
{
   lbl1.Text = DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss tt");
}

protected override void OnClosing(CancelEventArgs e)
{
   _IsShuttingDown = true;
   base.OnClosing(e);
}

また、フォームが閉じているとき、または奇妙なことが起こったときにループを終了するために、フォームにフィールドを追加しました。

私の元のコード:

if (lbl1.InvokeRequired)
{
    lbl1.Invoke((Action)(() => lbl1.Text = DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss tt")));
    Thread.Sleep(1000);
}
于 2012-09-13T01:51:45.303 に答える