C#-暂停后杀死任务

时间:2020-05-17 11:22:56

标签: c# multithreading asynchronous async-await timeout

我有此方法ExecuteAllAsync(),该方法使用字段List Jobs并异步执行list中的所有Jobs。我想设置一个超时来终止该作业并在需要很长时间或不再需要时停止执行。我尝试在以下代码中这样做:


        //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);
        }

这不起作用。我还尝试将Thread.Sleep(1000)放到ExecuteJob()函数中,以使所有任务超时,结果是只有部分作业超时而有些完全执行。我还使用秒表检查工作需要多长时间,我发现其中一些需要1秒钟以上。

当前超时设置为500毫秒,但将来每个任务将具有不同的超时值:

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

在为每个任务设置超时时,如何异步执行列表中的所有作业? 预先感谢。

2 个答案:

答案 0 :(得分:3)

您可以使用CancellationToken

您可以使用CancellationTokenSource创建一个,然后将超时传递给.CancelAfter(int);

https://docs.microsoft.com/en-us/dotnet/api/system.threading.cancellationtokensource.cancelafter?view=netcore-3.1

请确保检查您任务中的cancelledToken。

答案 1 :(得分:0)

您可以使用这种简单的方法:

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

请注意,您可以简单地使用Parallel.ForEach,它会为您处理多个线程,并根据执行计算机中可用内核的数量对其进行优化