I know that async functions are great because they don't block your UI thread, so the app can continue running while some long process is running.
Here's the problem my data repositories are all async. So I have functions like
public async Task<ObservableCollection<Categories>> GetItems() { CreateConnection(); return new ObservableCollection<Categories>(await connection.Table<Categories>().ToListAsync()); }
I then use the code like this
//List of categories public ObservableCollection<Cagegories> ocCategories; //List of categories public ObservableCollection<Products> ocProducts; //build an accessor for the repo public CategoriesRepository CategoryRepo => new CategoriesRepository(); public ProductsRepository ProductRepo => new ProductsRepository (); //Constuctor for page public ShowCategoryTable() { LoadTableData(); //combo box of categories cbCategories.DataSource = ocCategories; dtProducts.DataSource = ocProcucts; } public async void LoadTableData() { ocCategories = await CategoryRepo.GetItems(); ocProducts = await ProductRepo.GetItems(); }
When this code is called, it spawns off on another thread, as it should.
Here's the rub, the code that uses the result is executed before this call is finished, which will in turn cause a NullException
to be thrown, because the thread that is getting the data still has not returned yet.
I was under the impression that this is what the await
call was for. That this would in effect make an async
function become synchronous (but using a backing thread for the process).
I've already tried this too.
//Constuctor for page public ShowCategoryTable() { Initialize(); ConsumeData(); } public async void Initialize() { await LoadTableData(); // I've tried even using ConfigureAwait for this and still had the same results. } public void ConsumeData() { //combo box of categories cbCategories.DataSource = ocCategories; dtProducts.DataSource = ocProcucts; }
When this runs it reaches the await
it starts that thread, and immediately attempts to use the data, even when I have tried breaking it into separate async functions and calling them independently
I have tried the code with both ConfigureAwait
and even using true
and false
. But no matter what I do, it seems that my thread is not waiting for the data to return. I can write some really unpleasant code and use Task.Wait(xxx)
and make it wait 200ms or so. But that is really bad coding in my experience, and should be avoided like the plague.
The hard part becomes, how can I make these async DB calls execute and return before the UI consumes the data? effectively, how can I make async DB functions perform synchronously?
From what I've read it sounds like that's what await
is supposed to do, but it's failing to do so for me.