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.
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); }
Ended up writing this today and seems to be ok. Your usage could be:
await TaskEx.WaitUntil(isExcelInteractive);
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With