C#从主线程中暂停一个工作线程

时间:2017-10-17 08:41:16

标签: c# multithreading

所以,我想从主线程中暂停一个工作线程,如果我决定,我希望能够恢复它的活动。在此之前,我使用了myThread.Suspend()Resume(),但它已经已弃用而且不推荐不再使用它。

你们中有人能给我一个替代吗? 谢谢!

3 个答案:

答案 0 :(得分:2)

一种方法是使用ManualResetEventAutoResetEvent对象。等待信号的线程将阻塞,直到某些事件将调用事件对象上的Set()。

当然,这仅适用于控制在工作线程中执行的循环。

private ManualResetEvent runningWork = new ManualResetEvent(true);

public void Main()
{
    //

    // suspend
    runningWork.Reset();

    // resume
    runningWork.Set();

    //
}

public void Work()
{
    // long task
    while (!stop)
    {
        runningWork.WaitOne(/* optional timeout */);

        //worker task
    }
}

答案 1 :(得分:0)

我认为你错过了重点。不推荐使用Thread.PauseThread.Resume的原因是使用它们会导致一系列问题。无论线程在做什么,调用Thread.Pause都会在其轨道中暂停一个线程。它可能持有一把锁。只要它被暂停,它将继续保持锁定状态。它可能正在复制文件,执行数据库更新,执行时间关键任务,更新共享数据结构等。在任何这些或许多其他任务期间暂停线程可能会使程序,数据库,文件系统,甚至可能是处于不一致状态的操作系统。如果然后中止该线程,则会使该不一致状态成为永久状态。

换句话说,不要这样做。

如果您希望能够暂停和恢复线程,则需要对线程进行编码,以便它知道它可以暂停。你需要让它在暂停时合作。因此,不要在其轨道中停止线程,而是告诉线程您希望它尽早停止。

我所知道的最简单的方法是使用ManualResetEvent。这里的想法是您在设置状态下初始化事件。如果希望线程暂停,则清除该事件。然后在希望线程恢复时再次设置它。例如:

ManualResetEvent OkayToContinue = new ManualResetEvent(true);

// in your main thread

Thread myThread = CreateWorkerThread(...); // however you do that.

// pause the thread . . .
OkayToContinue.Reset();

// do whatever you want to do while the thread is suspended

// And then restart the thread
OkayToContinue.Set();

在工作线程中:

while (!done)
{
    // make sure it's safe to continue
    OkayToContinue.WaitOne();

    // do next step . . .
}

现在,如果您希望线程终止,通常使用CancellationToken。为此,您可以将其添加到主程序中:

CancellationTokenSource CancelToken = new CancellationTokenSource();

通常,您将CancelTokenSource.Token传递给线程,以便它无法访问CancelletionTokenSource对象,但是对于此示例,我将通过父对象。

// in your thread proc
do
{
    // do next step
    // Then check to see if paused or canceled
    OkayToContinue.WaitOne();
} while (!done && !CancelToken.Token.IsCancellationRequested);

这里的关键是你不要从线下拉出地毯。相反,你要告诉线程优雅地关闭。

答案 2 :(得分:-1)

private BackgroundWorker _bgWorker = new BackgroundWorker();

public void Main(string[] args)
{
    _bgWorker.DoWork += _bgWorker_DoWork;

    // We want to be able to cancel our installation, for whatever reason.
    _bgWorker.SupportsCancellation = true;

    _bgWorker.RunWorkerAsync();
}

private void _bgWorker_DoWork(object sender, DoWorkEventArgs e)
{
    while (!_bgWorker.CancellationPending)
    {
        // Do things for your install here.
    }

    // Display your dialog asking if they'd like to continue.
    if (!userWantsToContinue)
    {
        // Do rollback logic here.
        return;
    }
    else
    {
        // Do the rest of your install.
    }
}

这是使用BackgroundWorker执行此操作的粗略抛出示例,而不是您必须管理的单独线程。 BackgroundWorker还具有报告事件进度和使用事件报告线程工作完成的额外好处。

https://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker(v=vs.110).aspx