简体   繁体   English

C# - 超时后终止任务

[英]C# - Kill task after timout

I have this method ExecuteAllAsync() which uses the field List jobs and executes asynchronously all Jobs in the list.我有这个方法 ExecuteAllAsync(),它使用字段 List jobs 并异步执行列表中的所有 Jobs。 I want to set a timeout to kill the job and stop the execution if it takes to long or no longer necessary.我想设置一个超时来终止作业并在需要很长时间或不再需要时停止执行。 I tried doing so in the following code:我尝试在以下代码中这样做:


        //Execute all jobs async
        public async void ExecuteAllAsync()
        {
            if (jobs.Count()==0)
                return;
            List<Task> tasks = new List<Task>();
            foreach (Job job in jobs.ToArray())
            {
                int timeout = 500; 

                Task t = Task.Run(() => { 
                     ExecuteJob(job) // Do Work Here
                });
                tasks.Add(t);
                if (!t.Wait(timeout))
                     //Log Timeout Error
            }
            await Task.WhenAll(tasks);
        }

This doesn't work.这是行不通的。 I tried to also put Thread.Sleep(1000) in the ExecuteJob() Function to make all tasks timeout and and the result is that only some of the jobs timeout and some execute fully.我还尝试将 Thread.Sleep(1000) 放在 ExecuteJob() Function 中以使所有任务超时,结果是只有一些作业超时,一些作业完全执行。 I also use stopwatch to check how long the job takes and I see some of them takes more than 1 second.我还使用秒表来检查工作需要多长时间,我发现其中一些需要超过 1 秒。

Currently the timeout is set 500 ms but in the future each task will have different timeout value:目前超时设置为 500 毫秒,但将来每个任务将有不同的超时值:

int timeout = (int)(job.TimeToKill() - DateTime.Now).TotalMilliseconds

How do I execute all jobs in list asynchronously while setting a timeout to each task?如何在为每个任务设置超时的同时异步执行列表中的所有作业? Thanks in advance.提前致谢。

You could use a CancellationToken :您可以使用CancellationToken

You can create one with a CancellationTokenSource and then pass a timeout to .CancelAfter(int) ;您可以使用CancellationTokenSource创建一个,然后将超时传递给.CancelAfter(int)

https://learn.microsoft.com/en-us/do.net/api/system.threading.cancellationtokensource.cancelafter?view.netcore-3.1 https://learn.microsoft.com/en-us/do.net/api/system.threading.cancellationtokensource.cancelafter?view.netcore-3.1

Make sure to check the cancellationToken inside your task.确保检查任务中的 cancellationToken。

You can use this simple approach:您可以使用这种简单的方法:

public void ExecuteAll() //Note: since ExecuteJob is not async, this method not needs to be async anymore
{
    if (jobs.Count() == 0)
        return;

    int timeout = 500; 

    Parallel.ForEach(jobs, job => ExecuteJob(job, timeout);
}


public void ExecuteJob(Job job, int tiemout) //Your new ExecuteJob overload receiving a Timeout and using a CancellationToken internally
{
    using (var cts = new CancellationTokenSource(timeout))
    {
        foreach (var jobItem in job.ItemsToProcess) //Assuming you have something to do inside our job
        {
            if (cts.Token.IsCancellationRequested)
            {
                // ==> Log Timeout Error; cancel your job 
            }

            // Do your job
        }
    }
}

Note you can simply use Parallel.ForEach , it would take care for you about the multiple threads, optimizing them according to the numbers of cores available in the executing machine请注意,您可以简单地使用Parallel.ForEach ,它会照顾您的多个线程,根据执行机器中可用的内核数量优化它们

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

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