C# Wait until condition is true
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);
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
You can use thread waiting handler
private readonly System.Threading.EventWaitHandle waitHandle = new System.Threading.AutoResetEvent(false);
private 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
waitHandle.WaitOne();
Console.WriteLine("Excel is busy");
waitHandle.Reset();
// Do work
Console.WriteLine("YAY");
}
then some other job need to set your handler
void isExcelInteractive()
{
/// Do your check
waitHandle.Set()
}
Update: If you want use this solution, you have to call isExcelInteractive() continuously with specific interval:
var actions = new []{isExcelInteractive, () => Thread.Sleep(25)};
foreach (var action in actions)
{
action();
}