使用另一个线程从一个线程停止工作

时间:2010-06-18 16:11:15

标签: c# multithreading

不确定我的标题措辞是否合适,但无论如何:)

我有两个主题:需要完成工作的主线程,以及包含带进度条和取消按钮的表单的工作线程。在普通代码中,它将是另一种方式,但在这种情况下我不能这样做。

当用户点击取消按钮时,会显示一个提示,询问他是否要真正取消工作。问题是主线程上的工作仍在继续。我可以让主线程停止工作等等,但我希望它在提示单击“是”时停止工作。

示例:

// Main thread work starts here    
    t1 = new Thread(new ThreadStart(progressForm_Start));
    t1.Start();

    // Working
    for (i = 0; i <= 10000; i++)
    {
        semaphore.WaitOne();
        if (pBar.Running)
            bgworker_ProgressChanged(i);
        semaphore.Release();
        if (pBar.IsCancelled) break; 
    }

    t1.Abort(); 
// Main thread work ends here

// Start progress bar form in another thread
void progressForm_Start()
{
    pBar.Status("Starting");
    pBar.ShowDialog();
}

理论上我可以在cancelWatch()函数中包含一个提示符,但是在我实现这个类的任何地方我都必须这样做。

2 个答案:

答案 0 :(得分:2)

我有几个快速评论:

  1. 避免使用Thread.Abort() here's why
  2. 使您的主题成为后台主题:Thread.IsBackground = true(当您的应用程序退出时,这将自动退出该主题)。
  3. 以下是有关如何安全停止线程运行的详细讨论:Is it safe to use a boolean flag to stop a thread from running in C#

    要停止主线程的工作,你必须做这样的事情:

    boolean volatile isRunning = true;
    
    static void Main(...)
    {
        // ...
        // Working
        for (i = 0; i <= 10000; i++)
        {
            semaphore.WaitOne();
            if (!isRunning) break; // exit if not running
            if (pBar.Running)
                bgworker_ProgressChanged(i);
            semaphore.Release();
        }
        //...
        t1.Interrupt();// make the worker thread catch the exception
    }
    // 
    void cancelButton_Click(object sender, EventArgs e)
    {
        isRunning = false; // optimistic stop
        semaphore.Release();
    }
    

答案 1 :(得分:1)

我建议使用CancellationTokenSource,它可以处理这种复杂的情况。它是任务并行库的一部分,但实际上不必与Task个对象一起使用;它可以很容易地与旧式Thread对象一起使用。

当然,如果你有时间,我建议将主线程的工作定义为Task对象(使用TaskScheduler.FromCurrentSynchronizationContext在主UI线程上运行)。

请注意,以上所有内容均假定为.NET 4.0。如果您仍然停留在旧平台上,则只需要bool cancelled;字段保护lock或某些此类内容。提示:请勿致电Thread.Abort;这是邪恶的。