1

我们正在处理 Windows 服务 (.net 4.0) 中大文件的处理和上传。处理和上传步骤可能需要几分钟才能完成。管理员可以直接在数据库中将作业标记为已取消,但要在内存队列中清除它需要重新启动服务。目标是放弃该作业并在队列中选择下一个作业,而无需重新启动服务。这是我想要做的:

在主入口点,启动两个任务:

Task processTask = Task.Factory.StartNew(ProcessJob);

Task monitorTask = Task.Factory.StartNew(MonitorDB);

ProcessJob 会调用多个长时间运行的步骤,例如 ProcessFile、UploadFile。我们正在检查步骤之间的作业状态,但作业可能会卡在这些长时间运行的步骤之一中。

如果 monitorTask 检测到 DB 中的作业状态发生变化,它应该将其传达给主线程(通过异常或消息),以便主线程可以退出,将自己从处理队列中移除并允许队列中的下一个作业开始。没有等待不能得到异常但不能等待,因为需要并行运行这些任务。目前,我们并不关心 ProcessJob 中的某些同步步骤可能仍在进行并最终可能完成的事实。我们将在代码中处理它。

到目前为止,在我的所有应用程序中,我都使用 Task.ContinueWith 来判断成功和失败,但从来不需要与主线程进行通信。

4

2 回答 2

3

您可以通过BlockingCollection<T>.

这是我写的一个简单的例子。

BlockingCollection<string> queue =
    new BlockingCollection<string>();

// monitor thread.
Task.Factory.StartNew(() =>
{
    while (true)
    {
        Thread.Sleep(1000);
        queue.Add("event occured.");
    }
});

// main thread.
while (true)
{
    // blocks when no messages are in queue.
    string message = queue.Take();

    // kill process thread here.
}
于 2012-05-30T15:46:07.083 回答
1

您可以CancellationToken为此使用 a 。如果你看一下这个Task类,有一个重载,你可以传入一个CancellationToken. 在您的服务中存储对此令牌的引用,并让您的上传/处理例程定期检查令牌是否已被取消,如下所示:

if (yourToken.IsCancellationRequested)
    break;
于 2012-05-30T15:42:55.513 回答