简体   繁体   中英

C# - Kill task after timout

I have this method ExecuteAllAsync() which uses the field List jobs and executes asynchronously all Jobs in the list. 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. I also use stopwatch to check how long the job takes and I see some of them takes more than 1 second.

Currently the timeout is set 500 ms but in the future each task will have different timeout value:

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 :

You can create one with a CancellationTokenSource and then pass a timeout to .CancelAfter(int) ;

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.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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