多线程-WinForms事件中的中断线程

时间:2019-01-18 15:57:07

标签: c# multithreading winforms

我正在研究一个实现密码管理器的C#WinForms项目。我要包括的功能之一是允许密码保留在系统剪贴板中的超时时间。我实现了一个更新进度条的线程,然后在该线程终止之前清除剪贴板:

private void getPassword(int lifeInSeconds)
    {
        int maxLifeBarValue = lifeInSeconds * 10;

        Thread t = new Thread
        (delegate ()
        {
            //Initialize the progress bar
            Invoke((MethodInvoker)delegate
            {
                lifeBar.Maximum = maxLifeBarValue;
                lifeBar.Value = maxLifeBarValue;
                lifeBar.Visible = true;
                Clipboard.SetText(pd.getAccountPassword(lstAccounts.Text));
            });

            //Loop to update the progress bar
            for (int x = maxLifeBarValue; x >= 0; x--)
            {
                Thread.Sleep(100);
                Invoke((MethodInvoker)delegate
                {
                    lifeBar.Value = x;
                });
            }

            //Clear the system clipboard
            Clipboard.SetText(string.Empty);

            //Hide the progress bar when we're done
            Invoke((MethodInvoker)delegate
            {
                lifeBar.Visible = false;
            });
        });
        t.SetApartmentState(ApartmentState.STA);
        t.Start();
    }

这有效,但是我遇到的问题是,如果用户触发一个事件以复制另一个密码(或相同的密码;没关系),那么我们现在有2个线程在后台运行。事实证明,进度条正在“翻转”,可以说是每个线程都在独立更新其值。

当用户再次单击“复制密码”按钮时,是否可以检测并终止原始线程(如果存在)?

1 个答案:

答案 0 :(得分:1)

您可以保留对该线程的引用,然后在启动新线程之前中止该线程。像这样:

private Thread passwordClearThread = null;

private void getPassword(int lifeInSeconds)
{
  int maxLifeBarValue = lifeInSeconds * 10;

  if (passwordClearThread != null && passwordClearThread.IsAlive)
  {
    passwordClearThread.Abort();
    passwordClearThread.Join();
  }

  passwordClearThread = new Thread
  (() =>
  {
    //Initialize the progress bar
    Invoke((MethodInvoker)delegate
    {
      lifeBar.Maximum = maxLifeBarValue;
      lifeBar.Value = maxLifeBarValue;
      lifeBar.Visible = true;
      Clipboard.SetText(pd.getAccountPassword(lstAccounts.Text));
    });

    //Loop to update the progress bar
    for (int x = maxLifeBarValue; x >= 0; x--)
    {
      Thread.Sleep(100);
      Invoke((MethodInvoker)delegate
      {
        lifeBar.Value = x;
      });
    }

    //Clear the system clipboard
    Clipboard.Clear();

    //Hide the progress bar when we're done
    Invoke((MethodInvoker)delegate
    {
      lifeBar.Visible = false;
    });
  });
  passwordClearThread.SetApartmentState(ApartmentState.STA);
  passwordClearThread.Start();
}