I would like to implement an async version of the Device.StartTimer method. The reason is that I need the callback to wait for the boolean result of an async method to be returned.
I can't figure out how to do this, because I can't see how to await the TaskCompletionSource's task. The result is that the boolean value is returned immediately.
Device.StartTimer(TimeSpan.FromMilliseconds(500), () =>
{
var retVal = false;
Device.BeginInvokeOnMainThread(async () =>
{
TaskCompletionSource<bool> tcs = new();
retVal = await this.RefreshAsync().ConfigureAwait(false);
tcs.TrySetResult(retVal);
});
// How to await the TaskCompletionSource's Task ?
return retVal;
});
EDIT: The business problem that I'm trying to solve, is in iOS specific code, displaying a toast and waiting for its animation to complete (alpha = 0).
Because the animation is completely asynchronous, I'm using a TaskCompletionSource and set its result in the completion handler to await the task on the outside.
Here is the code:
private static Task ShowAlertAsync(string message, double seconds, Alignements alignements)
{
var preferredStyle = UIAlertControllerStyle.Alert;
if ((alignements & Alignements.Bottom) != 0)
{
preferredStyle = UIAlertControllerStyle.ActionSheet;
}
TaskCompletionSource<bool> tcs = new();
var toast = UIAlertController.Create("", message, preferredStyle);
UIApplication.SharedApplication.KeyWindow.RootViewController.PresentViewController(toast, true, () =>
{
UICubicTimingParameters timing = new(UIViewAnimationCurve.EaseIn);
UIViewPropertyAnimator animator = new(seconds, timing);
animator.AddAnimations(() => { toast.View.Alpha = 0; });
animator.AddCompletion((pos) =>
{
toast.DismissViewController(true, null);
toast.Dispose();
toast = null;
tcs.TrySetResult(true);
});
animator.StartAnimation();
});
return tcs.Task;
}
Basicaly, RefreshAsync in the previous bloc of code is awaiting ShowAlertAsync.