Saturday, 16 April 2016

Parallel Task With Time Expiration (Pseudo Timeout)

Hi, today I will write about mini task I was doing at work. To keep the story short, I have been asked to refactor code to control the maximum concurrency spawned from a method, and the method should run in a certain amount of time.

Here is the code before refactoring:

  public void PerformMultiTask(IEnumerable<string> ids)
  {
    foreach(string id in ids)
    {
      Task.Run(()=>PerformSingleTask(id));
    }
  }

The reason for the time limit is because the scheduler which triggers the method will run in intervals. So, we need to make sure that method execution finishes before the scheduler starts again. We also want the ability to control the concurrency of the execution.

Here is the code after refactoring:

  public void PerformMultiTask(
    int timeLimitInSeconds, 
    int maxConcurrency,
    IEnumerable<string> ids)
  {
     DateTime timeLimit = DateTime.UtcNow.Add(new TimeSpan(0,0,0,timeLimitInSeconds));
                        
     Parallel.ForEach(
      ids,
      new ParallelOptions() { MaxDegreeOfParallelism = maxConcurrency },
      (id, loopState) =>
      {
        if (DateTime.UtcNow < timeLimit)
          PerformSingleTask(id);
        else
          loopState.Stop();
      });
  }

I use Parallel.ForEach method which accepts three parameters:
  1. the list IEnumerable<T>
  2. ParallelOptions instance
  3. Action(T,ParallelLoopState)
In the above example T is a string type. We create a ParallelOptions instance and specify MaxDegreeOfParallelism to control the maximum concurrency of the parallel loop. The variable loopstate is a ParallelLoopState instance, which is passed as an argument and used by the action to stop the whole parallel loop, once the expiration(or time Limit) has been reached.

Feel free to comment or to suggest improvement of the code.