为什么这项任务会毫不拖延地退出?

时间:2014-07-14 13:30:35

标签: c# multithreading task-parallel-library .net-4.5

我一直在使用System.Threading.Tasks.Task.Run()取得了巨大的成功。我最近发现我的一个进程过早退出,因为任务没有完成。显然,我没有第一个线索,System.Threading.Tasks.Task.Run()实际上是如何工作的,我的100,000多行C#代码(三个Windows服务,Web应用程序,数据库和内存进程间缓存)工作原理纯粹的运气。这是代码的简化版本。为什么在没有执行延迟的情况下退出流程?

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace TaskWaitDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            Task.Run(() =>
            {
                while (true)
                {
                    try
                    {
                        Task.Delay(60 * 1000).Wait();
                        // In my actual code I perform real computation right here after the wait.
                        Console.WriteLine("why does this line never execute???");
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine(ex.Message);
                    }
                }
            });
        }
    }
}

修改

尝试拥抱与线程无关的任务世界,我将任务用于两个主要目的:1)将工作排队到线程池,以及2)异步处理周期性任务。我上面的例子是一个过度简化的尝试来展示一个周期性任务的例子。在我的实际应用中,While (true) { ... }实际上更像是while (!_shutdown) { ... }

各种评论和答案都建议只是等待任务,但在我的实际应用程序中,主线程在启动任务后可能有也可能没有事可做,而且不能简单地等待我的周期性任务而不会永远阻止。

在线程的旧时代,线程A将启动线程B,然后如果没有任何事情可以优雅地退出,让线程B快乐地做它的事情并且进程仍在运行。

似乎在勇敢的新任务世界中,线程A运行任务B(将一些工作(可能是周期性的)排队到线程池中,然后如果没有任何事情要做,则可以优雅地退出。然后,框架将任务B(以及显然通过任务排队到线程池的任何其他工作)扔到位桶中,并且该过程终止。似乎对我不利。

我想我的答案是使用好的旧线程进行周期性任务,并希望并祈祷在允许应用程序关闭之前,线程池队列中的所有即发即弃任务都已完成。

2 个答案:

答案 0 :(得分:4)

你运行while(true),是的,这是正确的,但你在另一个线程上运行它。

相反,主线程会在Main内全程运行并退出应用。

        static void Main(string[] args)
        {

            //MAIN THREAD BOUNDS
            //LAUNCH THE TASK AND GO AHEAD
            var task = Task.Run(() => (EDIT)
            {    
                //SECOND THREAD BOUNDS 
                while (true)
                {
                  ...
                }
               //--------------
            });
            task.Wait(); (EDIT) //WAIT FOR TASK COMPLETION  !!!!

            //NOTHING MORE TO DO, SO EXIT APP AND KILL Task.Run THREAD
        }

修改

如果您需要等待完成,只需使用Task.Wait,就像编辑后的代码一样。在这个具体的例子中,它没有任何意义,这并不意味着它不会在你的中。

答案 1 :(得分:0)

您的任务的更好结构将是:

static void Main(string[] args)
{
    var task = new Task(() => 
    {         
        while (true)
        {
            Console.WriteLine("Computing..");
            Thread.Sleep(1000);
        }
    });
    task.Start();
    task.Wait(); //Wait for the task to finish
}