Microsoft proposes another way to implement this, namely by using a cancellationTokenSource and a cancellationToken.
Microsoft about Task Cancellation
StackOverflow also has some topics about this:
CancellationToken and CancellationTokenSource-How to use it?
Translated to your problem, the caller wouldn't pass the delegate Function, but a System.Threading.CancellationToken object. Instead of calling the delegate, the Wait function regularly checks the CancellationToken object whether cancellation is requested.
This method is really very similar to yours, except that it is a more standard pattern. The real bonus is, that you can use cancel all tasks that use a token from the same source in one call. Besides it has a built in timeout feature.
Another advantage is that the reason to cancel is decided outside your function, it can be a timeout, or because BooleanFunction returns true, maybe even because your program stops etc. Even if in a future version a new reason to stop waiting is introduced, your wait function doesn't have to change. All it does is do its work and regularly check if CancellationIsRequested.
Example code:
Your wait function doesn't do a lot but wait. I guess you simplified this, because if that was all it really needed to do, I guess you had used a System.Timer. Let's assume you have to do something
I have a form with two buttons: buttonStartWait and buttonCancelWait. When pressed, buttonStartWait will start the Wait, while buttonCancelWait will cancel the waiting.
If we had used your method, buttonCancelWait would make that the delegate returned true.
The code would be like follows (I've also changed your usage of Ticks into TimeSpan to make it easier to read)
private CancellationTokenSource tokenSource = null;
private async void OnButtonStartWait_clicked(object sender, ...)
{
this.buttonStartWait.Enabled = false;
TimeSpan waitTime = GetWaitTime();
this.tokenSource = new tokenSource(waitTime);
// this makes sure that after waitTime cancellation is requested
await this.Wait(this.TokenSource.Token);
this.buttonstartWait.Enabled = true;
}
private async Task<bool> Wait(CancellationToken token)
{
while (!token.IsCancellationRequested)
{ // do the thing your function is supposed to do.
DoSomethingShort();
// if this function takes some time, pass the token to it
// and let it regularly check if cancellation is requested
DoSomethingLonger(token);
// or consider starting a Task which regularly checks
// if cancellation is requested
await Task.Run( () => DoSomethingLonger(token), token);
}
return token.IsCancellationRequested;
}
// a Wait function that really doesn't do anything but wait
// until cancellation is requested.
private async Task<bool> Wait(CancellationToken token)
{
while (!token.IsCancellationRequested)
{ // wait a short while
await Task.Wait(TimeSpan.FromSeconds(0.1), token;
}
return token.IsCancellationRequested;
}
private async void OnButtonCancelWait_clicked(object sender, ...)
{
if (this.TokenSource != null)
{
this.TokenSource.Cancel();
}
}