如何向应用程序添加暂停/恢复功能?

Ars*_*ray 6 c# multithreading

我正在编写一个应用程序,其中大部分工作都是由后台线程(10 - 500个线程)完成的.

我想添加暂停/恢复功能.

之前,你可以使用Thread.Suspend和Thread.Resume来做到这一点.但是这些功能现在已经过时了.

还有什么可以让我同样轻松地做同样的事吗?

我在c#中编写软件

Jim*_*hel 2

在用 C# 编写了一个高性能爬虫之后,我可以有权威地说,显式管理数十或数百个线程并不是最好的方法。可以做到(我做到了),但是非常痛苦。

话是这么说。。。

如果你的应用程序是按照我的想法编写的,那么每个线程都会执行如下操作:

while (!Shutdown)
{
    // get next url to crawl from somewhere
    // download the data from that url
    // do something with the data
}
Run Code Online (Sandbox Code Playgroud)

在下载之间暂停线程非常容易。我建议创建两个ManualResetEvent实例:一个用于继续,一个用于关闭。这些是static为了让所有爬虫线程都可以访问它们:

static ManualResetEvent ShutdownEvent = new ManualResetEvent(false);
static ManualResetEvent ContinueEvent = new ManualResetEvent(true);
Run Code Online (Sandbox Code Playgroud)

然后,每个线程WaitAny循环使用:

WaitHandle[] handles = new WaitHandle[] { ShutdownEvent, ContinueEvent };
while (true)
{
    int handle = WaitHandle.WaitAny(handles);  // wait for one of the events
    if (handle == -1 || handle >= handles.Length)
    {
        throw new ApplicationException();
    }

    if (handles[handle] = ShutdownEvent)
       break;  // shutdown was signaled

    if (handles[handle] == ContinueEvent)
    {
        // download the next page and do something with the data
    }
}
Run Code Online (Sandbox Code Playgroud)

请注意,当我定义handles数组时,我ShutdownEvent首先指定了。原因是,如果多个项目被发出信号,WaitAny则返回与发出信号的对象相对应的最低索引。如果数组以其他顺序填充,那么您将无法在不先暂停的情况下关闭。

现在,如果您希望关闭线程,请调用ShutdownEvent.Set. 如果您希望线程暂停,请调用ContinueEvent.Reset当您希望线程恢复时,请调用ContinueEvent.Set

在下载过程中暂停有点困难。这是可以做到的,但问题是,如果暂停时间太长,服务器可能会超时。然后,您必须从头开始重新下载,或者,如果服务器和您的代码支持,请从您停止的位置重新开始下载。这两种选择都相当痛苦,所以我不建议尝试在下载过程中暂停。