简体   繁体   English

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

[英]Passing exception or message from thread/task to main thread

We are dealing with processing and uploading of large files in windows service (.net 4.0). 我们正在Windows服务(.net 4.0)中处理和上传大文件。 Process and upoload steps can take minutes to complete. 处理和上传步骤可能需要几分钟才能完成。 Admin has the ability to mark job as cancelled, directly in database but to clear in memory queue it requires service restart. 管理员可以直接在数据库中将作业标记为已取消,但要清除内存队列中的作业则需要重新启动服务。 Goal is to abandon that job and pick next job in queue without service restart. 目标是放弃该作业并在不重新启动服务的情况下选择队列中的下一个作业。 Here's what I want to do: 这是我想做的:

In main entry point, start two tasks: 在主入口点,启动两个任务:

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

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

ProcessJob would call multiple long running steps like ProcessFile, UploadFile. ProcessJob将调用多个长时间运行的步骤,例如ProcessFile,UploadFile。 We are checking for job status between the steps but job may be stuck in one of these long running steps. 我们正在检查步骤之间的作业状态,但是作业可能卡在了这些长时间运行的步骤之一中。

If monitorTask detects job status change in DB, it should communicate that to main thread (through exception or message), so that main thread can quit, removing itself from the processing queue and allow next job in queue to start. 如果monitorTask在DB中检测到作业状态更改,则应(通过异常或消息)将其传达给主线程,以便主线程可以退出,将自身从处理队列中删除并允许队列中的下一个作业启动。 Without Wait cannot get to exception but cannot wait because need to run these tasks in parallel. 如果不等待,则不能进入异常,但不能等待,因为需要并行运行这些任务。 At this time we are not concerned with the fact that some synch step in ProcessJob may still be going on and it may eventually complete. 目前,我们不担心ProcessJob中的某些同步步骤可能仍在进行并且最终可能完成的事实。 We would handle that in code. 我们将用代码来处理。

So far in all of my applications, I have used Task.ContinueWith for success and failure, but never had to communicate back to main thread. 到目前为止,在我所有的应用程序中,我都使用Task.ContinueWith进行成功和失败,但从未必须与主线程进行通信。

You could communicate between the monitor thread and the main thread through a BlockingCollection<T> . 您可以通过BlockingCollection<T>在监视器线程和主线程之间进行通信。

Here's a simple example I wrote. 这是我写的一个简单示例。

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.
}

You can use a CancellationToken for this. 您可以为此使用CancellationToken If you look at the Task class, there is an overload where you can pass in a CancellationToken . 如果查看Task类,则有一个重载,您可以在其中传递CancellationToken Store a reference to this token in your service and simply have your upload/process routine periodically check if the token has been cancelled like so: 在您的服务中存储对此令牌的引用,只需让您的上传/处理例程定期检查令牌是否已被取消,如下所示:

if (yourToken.IsCancellationRequested)
    break;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM