Task.Factory.StartNew中的随机任务永远不会完成 [英] Random tasks from Task.Factory.StartNew never finishes

查看:376
本文介绍了Task.Factory.StartNew中的随机任务永远不会完成的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在通过Task.Factory方法使用Async等待.

I am using Async await with Task.Factory method.

public async Task<JobDto> ProcessJob(JobDto jobTask)
{
    try
    {
        var T = Task.Factory.StartNew(() =>
        {
            JobWorker jobWorker = new JobWorker();
            jobWorker.Execute(jobTask);
        });

        await T;
    }

我正在这样的循环内调用此方法

This method I am calling inside a loop like this

for(int i=0; i < jobList.Count(); i++)
{
    tasks[i] = ProcessJob(jobList[i]);
}

我注意到的是,新任务在Process Explorer中打开,它们也开始工作(基于日志文件).然而,在十个有时八或七个完成中.其他人再也不会回来了.

What I notice is that new tasks opens up inside Process explorer and they also start working (based on log file). however out of 10 sometimes 8 or sometimes 7 finishes. Rest of them just never come back.

  1. 为什么会这样?
  2. 他们超时了吗?在哪里可以为我的任务设置超时时间?

更新

基本上,我希望每个任务一被调用就开始运行,并等待对AWAIT T关键字的响应.我在这里假设一旦他们完成,每个人都会回到Await T并进行下一步行动.我很高兴看到10项任务中有7项的结果,但是其中3项没有回来.

Basically above, I would like each Task to start running as soon as they are called and wait for the response on AWAIT T keyword. I am assuming here that once they finish each of them will come back at Await T and do the next action. I am alraedy seeing this result for 7 out of 10 tasks but 3 of them are not coming back.

谢谢

推荐答案

首先,让我们制作代码的可复制版本.这不是实现您正在做的事情的最佳方法,而是向您展示代码中正在发生的事情!

First, let's make a reproducible version of your code. This is NOT the best way to achieve what you are doing, but to show you what is happening in your code!

我将使代码与您的代码几乎相同,除了我将使用简单的int而不是您的JobDto,并且在完成工作Execute()之后,我将在一个文件中编写一个我们可以验证的文件之后.这是代码

I'll keep the code almost same as your code, except I'll use simple int rather than your JobDto and on completion of the job Execute() I'll write in a file that we can verify later. Here's the code

public class SomeMainClass
{
    public void StartProcessing()
    {
        var jobList = Enumerable.Range(1, 10).ToArray();
        var tasks = new Task[10];
        //[1] start 10 jobs, one-by-one
        for (int i = 0; i < jobList.Count(); i++)
        {
            tasks[i] = ProcessJob(jobList[i]);
        }
        //[4] here we have 10 awaitable Task in tasks
        //[5] do all other unrelated operations
        Thread.Sleep(1500); //assume it works for 1.5 sec
        // Task.WaitAll(tasks); //[6] wait for tasks to complete
        // The PROCESS IS COMPLETE here
    }

    public async Task ProcessJob(int jobTask)
    {
        try
        {
            //[2] start job in a ThreadPool, Background thread
            var T = Task.Factory.StartNew(() =>
            {
                JobWorker jobWorker = new JobWorker();
                jobWorker.Execute(jobTask);
            });
            //[3] await here will keep context of calling thread
            await T; //... and release the calling thread
        }
        catch (Exception) { /*handle*/ }
    }
}

public class JobWorker
{
    static object locker = new object();
    const string _file = @"C:\YourDirectory\out.txt";
    public void Execute(int jobTask) //on complete, writes in file
    {
        Thread.Sleep(500); //let's assume does something for 0.5 sec
        lock(locker)
        {
            File.AppendAllText(_file, 
                Environment.NewLine + "Writing the value-" + jobTask);
        }
    }
}

仅运行StartProcessing()之后,这就是我在文件中得到的内容

After running just the StartProcessing(), this is what I get in the file

Writing the value-4
Writing the value-2
Writing the value-3
Writing the value-1
Writing the value-6
Writing the value-7
Writing the value-8
Writing the value-5

因此,已完成8/10个工作.显然,每次运行此命令时,编号和顺序可能都会更改.但是,关键是,所有工作都没有完成!

So, 8/10 jobs has completed. Obviously, every time you run this, the number and order might change. But, the point is, all the jobs did not complete!

现在,如果我取消对步骤[6] Task.WaitAll(tasks);的注释,这就是我在文件中得到的内容

Now, if I un-comment the step [6] Task.WaitAll(tasks);, this is what I get in my file

Writing the value-2
Writing the value-3
Writing the value-4
Writing the value-1
Writing the value-5
Writing the value-7
Writing the value-8
Writing the value-6
Writing the value-9
Writing the value-10

所以,我所有的工作都在这里完成!

So, all my jobs completed here!

代码注释中已经解释了为什么代码具有这种行为.要注意的主要事情是,您的任务在基于ThreadPoolBackground线程中运行.因此,如果您不等待它们,它们将在MAIN进程结束且主线程退出时被杀死!

Why the code is behaving like this, is already explained in the code-comments. The main thing to note is, your tasks run in ThreadPool based Background threads. So, if you do not wait for them, they will be killed when the MAIN process ends and the main thread exits!!

如果您仍然不想在那里等待任务,则可以从第一个方法返回任务列表,并在过程结束时返回await任务,类似这样

If you still don't want to await the tasks there, you can return the list of tasks from this first method and await the tasks at the very end of the process, something like this

public Task[] StartProcessing()
{
    ...
    for (int i = 0; i < jobList.Count(); i++)
    {
        tasks[i] = ProcessJob(jobList[i]);
    }
    ...
    return tasks;
}

//in the MAIN METHOD of your application/process
var tasks = new SomeMainClass().StartProcessing();
// do all other stuffs here, and just at the end of process
Task.WaitAll(tasks);

希望这可以消除所有的混乱.

Hope this clears all confusion.

这篇关于Task.Factory.StartNew中的随机任务永远不会完成的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆