使用AutoResetEvent.WaitOne()和.Set()暂停后台线程

时间:2013-04-14 13:25:34

标签: c# multithreading autoresetevent

我有以下代码。我正在尝试为主窗体创建按钮,可以暂停,继续并停止下载器运行的后台线程(私有线程线程)

Form1.cs的

private AutoResetEvent waitHandle = new AutoResetEvent(true);
private Thread thread;

        private void ThreadJob()
        {
            Downloader download = new Downloader();
            download.runDownloader();
        }

        // THREADS button1 is "Download now"-button
        private void button1_Click(object sender, EventArgs e)
        {
            ThreadStart job = new ThreadStart(ThreadJob);
            thread = new Thread(job);
            thread.IsBackground = true;
            thread.Start();
        }

此代码在Windows窗体上运行。我有所有这些动作的按钮(暂停,继续,停止)

暂停和继续按钮在表单上有代码

private void btnPause_Click(object sender, EventArgs e)
{
    waitHandle.WaitOne(); // Need to pause the background thread
}

 private void btnContinue_Click(object sender, EventArgs e)
    {
        waitHandle.Set(); // Need to continue the background thread
    }

问题是按暂停按钮会冻结主窗体而不是后台线程。

1 个答案:

答案 0 :(得分:4)

runDownloader()必须能够暂停。

需要定期在等待句柄上调用waitHandle.WaitOne()

你的WaitHandle必须是ManualResetEvent,而不是AutoResetEvent,你应该初始化它以便发出信号(除非你想让你的线程处于“暂停”状态)。

您还必须按如下方式更改按钮处理程序:

private void btnPause_Click(object sender, EventArgs e)
{
    waitHandle.Reset(); // Need to pause the background thread
}

private void btnContinue_Click(object sender, EventArgs e)
{
    waitHandle.Set(); // Need to continue the background thread
}

这意味着您必须能够将waitHandle传递给线程,以便它可以等待它。

但是,自.Net 4以来,有更好的方法来管理线程取消,即使用CancellationTokenSourceCancellationToken

有关详细信息,请参阅this Microsoft article