Home > Mobile >  Xamarin Device.BeginInvokeOnMainThread not asynch within lambda
Xamarin Device.BeginInvokeOnMainThread not asynch within lambda

Time:02-18

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;
  • Related