I have a Xamarin forms application that populates a collectionView with data every 10 seconds. I am however having a hard time getting this to work asynchronously. How can I get 'Device.BeginInvokeOnMainThread()' lambda to run asynchronously within the 'Device.StartTimer()' lambda?
protected override async void OnAppearing()
{
base.OnAppearing();
try
{
Device.StartTimer(TimeSpan.FromSeconds(10), async () =>
{
//1. Cannot await void
await Device.BeginInvokeOnMainThread(UpdateDataAsync);
//2. Cannot convert async lambda expression to delegate type 'Func<bool>'
await Task.Run(() => Device.BeginInvokeOnMainThread(UpdateDataAsync));
Device.BeginInvokeOnMainThread(() =>
{
//3. cannot await method group
await UpdateDataAsync;
});
return true;
});
}
catch (Exception ex)
{
throw ex;
}
}
public async void UpdateDataAsync()
{
var data = await dataUpdateService.GetUpdatedDataAsync();
collectionView.ItemsSource = data;
}
CodePudding user response:
I guess you could use the async version of BeginInvokeOnMainThread:
await Xamarin.Forms.Device.InvokeOnMainThreadAsync(() => { });
This is a task that will take a Func<T>
no need to add Task.Run before it FYI.
CodePudding user response:
Creating a TaskCompletionSource solve your problem.
var tcs = new TaskCompletionSource<bool>();
Device.BeginInvokeOnMainThread(async () =>
{
try
{
var result = await UpdateDataAsync;
tcs.TrySetResult(result);
}
catch (Exception ex)
{
tcs.TrySetException(ex);
}
});
return tcs.Task;