将异常或消息从线程/任务传递到主线程

时间:2012-05-30 15:24:31

标签: c# multithreading task-parallel-library task

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

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

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

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

ProcessJob会调用多个长时间运行的步骤,如ProcessFile,UploadFile。我们正在检查这些步骤之间的工作状态,但是工作可能会停留在其中一个长期运行的步骤中。

如果monitorTask检测到DB中的作业状态更改,它应该将其传递给主线程(通过异常或消息),以便主线程可以退出,从处理队列中删除自己并允许队列中的下一个作业启动。没有Wait就无法获得异常但不能等待,因为需要并行运行这些任务。 此时我们并不关心ProcessJob中的某些同步步骤可能仍在进行并且最终可能完成的事实。我们会在代码中处理它。

到目前为止,在我的所有应用程序中,我使用了Task.ContinueWith来获得成功和失败,但从未必须与主线程进行通信。

2 个答案:

答案 0 :(得分:2)

您可以通过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.
}

答案 1 :(得分:1)

您可以使用CancellationToken。如果您查看Task课程,可能会传输CancellationToken。在您的服务中存储对此令牌的引用,只需让您的上传/处理例程定期检查令牌是否已被取消,如下所示:

if (yourToken.IsCancellationRequested)
    break;