Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# Wait until condition is true

Tags:

c#

loops

I am trying to write a code that executes when a condition is met. Currently, I am using while...loop, which I know is not very efficient. I am also looking at AutoResetEvent() but i don't know how to implement it such that it keeps checking until the condition is true.

The code also happens to live inside an async method, so may be some kind of await could work?

private async void btnOk_Click(object sender, EventArgs e) {         // Do some work         Task<string> task = Task.Run(() => GreatBigMethod());         string GreatBigMethod = await task;          // Wait until condition is false         while (!isExcelInteractive())         {             Console.WriteLine("Excel is busy");         }          // Do work         Console.WriteLine("YAY");  }       private bool isExcelInteractive()     {         try         {             Globals.ThisWorkbook.Application.Interactive = Globals.ThisWorkbook.Application.Interactive;             return true; // Excel is free         }         catch         {             return false; // Excel will throw an exception, meaning its busy         }     } 

I need to find a way to keep checking isExcelInteractive() without CPU stuck in a loop.

Note: There is no event handler in Excel that would be raised when it is not in edit mode.

like image 830
Keylee Avatar asked Mar 17 '15 00:03

Keylee


Video Answer


2 Answers

At least you can change your loop from a busy-wait to a slow poll. For example:

    while (!isExcelInteractive())     {         Console.WriteLine("Excel is busy");         await Task.Delay(25);     } 
like image 125
Ben Voigt Avatar answered Sep 16 '22 14:09

Ben Voigt


Ended up writing this today and seems to be ok. Your usage could be:

await TaskEx.WaitUntil(isExcelInteractive);

code (including the inverse operation)

public static class TaskEx {     /// <summary>     /// Blocks while condition is true or timeout occurs.     /// </summary>     /// <param name="condition">The condition that will perpetuate the block.</param>     /// <param name="frequency">The frequency at which the condition will be check, in milliseconds.</param>     /// <param name="timeout">Timeout in milliseconds.</param>     /// <exception cref="TimeoutException"></exception>     /// <returns></returns>     public static async Task WaitWhile(Func<bool> condition, int frequency = 25, int timeout = -1)     {         var waitTask = Task.Run(async () =>         {             while (condition()) await Task.Delay(frequency);         });          if(waitTask != await Task.WhenAny(waitTask, Task.Delay(timeout)))             throw new TimeoutException();     }      /// <summary>     /// Blocks until condition is true or timeout occurs.     /// </summary>     /// <param name="condition">The break condition.</param>     /// <param name="frequency">The frequency at which the condition will be checked.</param>     /// <param name="timeout">The timeout in milliseconds.</param>     /// <returns></returns>     public static async Task WaitUntil(Func<bool> condition, int frequency = 25, int timeout = -1)     {         var waitTask = Task.Run(async () =>         {             while (!condition()) await Task.Delay(frequency);         });          if (waitTask != await Task.WhenAny(waitTask,                  Task.Delay(timeout)))              throw new TimeoutException();     } } 

Example usage: https://dotnetfiddle.net/Vy8GbV

like image 41
Sinaesthetic Avatar answered Sep 16 '22 14:09

Sinaesthetic