2

I have a method that contains an infinite loop. I call that method from main method and I want to cancel it if it takes more that 2 seconds. I tried these approaches

Task.WhenAny with cancellation of the non completed tasks and timeout

How can I cancel Task.WhenAll?

How to cancel a task using a CancellationToken and await Task.WhenAny

and lots of other links, but non has worked. here is my code

static void Main(string[] args)
{
   var cts = new CancellationTokenSource(2000);   
   var task = Task.Run(() => RunTask(), cts.Token);
   await task;
}

public static void RunTask()
{
   while (true)
   {
     Console.WriteLine("in while");
   }
}

I also tried to cancel my token but it didn't work. It is not possible to Dispose the task. I don't have access to RunTask source code. I just can run it. I cannot send CancellationToken to my method. How can I terminate RunTask() method?

Mohammad Taherian
  • 1,622
  • 1
  • 15
  • 34
  • Why can't you _send_ the token to your method? – ZorgoZ Nov 08 '19 at 19:26
  • Because I don't have access to that source code. Users can come and write their own code. – Mohammad Taherian Nov 08 '19 at 19:29
  • I don't get it. If there is no way you can control the code you are executing, then you need a higher level of segregation - execute it in a process. Otherwise, you will have huge problems. – ZorgoZ Nov 08 '19 at 19:32
  • I want to run it in a task and if it takes more than x seconds or milliseconds, I cancel it. I think this is the main concept of `CancellationToken`. – Mohammad Taherian Nov 08 '19 at 19:36
  • 1
    CancellationToken is collaborative: it suggests the task to finish its job. But the task can simply ignore it. So if the users can write whatever they want, then you can't rely on them to take the CancellationCoken into consideration. You simply can't. Then you need to take more harsh measures. – ZorgoZ Nov 08 '19 at 19:39
  • Things work differently than you think. The Action delegate has no access to the CancellationToken since it is a void FFF() method. The method therefore has no way to potentially check if someone wants to cancel it. The CancellationToken is used to prevent executing chained tasks registered with Task.ContinueWith which you do not have. This code does nothing with the CancellationToken and can be removed. – Alois Kraus Nov 08 '19 at 19:43
  • @AloisKraus you are right. But haw can I terminate that method in this case? – Mohammad Taherian Nov 08 '19 at 20:27
  • @MohammadTaherian: You can always call Term..... Just kidding. You cannot achieve that in a sane way without corrupting thread data and application state. – Alois Kraus Nov 08 '19 at 20:33
  • @AloisKraus I also tried to use `thread.Abort()` but it is not supported in `.net core 2.2` – Mohammad Taherian Nov 08 '19 at 20:36

2 Answers2

2

Cancellation tokens are a way to request cancellation. It's up to the running code to accept that request and actually stop the work. It's not like killing a process. For example, if you had something like:

public static void RunTask(CancellationToken cancellationToken)
{
   while (!cancellationToken.IsCancellationRequested)
   {
     Console.WriteLine("in while");
   }
}

Then, when it's canceled, the loop will end. However, given that the current code doesn't offer any method of canceling and you cannot modify it, then there is no way to cancel it.

Chris Pratt
  • 232,153
  • 36
  • 385
  • 444
0

What about this approach:

static void Main(string[] args)
{
   var cts = new CancellationTokenSource(2000);   
   var task = Task.Run(() => RunTask(cts.Token), cts.Token);
   await task;
}

public static void RunTask(CancellationToken token)
{
   while (!token.IsCancellationRequested)
   {
     Console.WriteLine("in while");
   }
}
ZorgoZ
  • 2,974
  • 1
  • 12
  • 34