Reputation: 61
I have code that gets executed when a ListView
item is selected. Since this code can take a noticeable amount of time to execute I want to display an ActivityIndicator
while it is running.
I have read through a lot of posts about the ActivityIndicator
and I believe I have it setup correctly. I'm pretty sure my problem is due to the running code blocking the UI thread since the UI freezes completely during the process.
I've worked through every variation I have been able to find for using async/await with no luck so I'm assuming that I am still doing something incorrectly.
Here is my code:
private ListItem selectedList;
public ListItem SelectedList
{
get
{
return selectedList;
}
set
{
if (selectedList != value)
{
var oldValue = selectedList;
selectedList = value;
buildThisList();
}
}
}
private async void buildThisList()
{
StatusBarIsVisibile = true;
ThisList = Task.Run(async () =>
{
return await buildBnBList(SelectedList, selectedLocation,
thisYearList.ListId)
.ConfigureAwait(false);
}).Result; // 1.8 seconds
StatusBarIsVisibile = false;
ThisList.MainVM = this;
ThisList.BuildView();
PIShowListHeaderText = SelectedList.Title.Trim();
}
private async Task<BnBList> buildBnBList(ListItem pSelectedList, State pselectedLocation, int pListId)
{
BnBList newList = new BnBList(pSelectedList, pselectedLocation, pListId);
List<BirdsnBflysMaster> bbfList =
App.BnBRepo.GetBirdsnBflys(selectedList.ListType); // 1.3 seconds
Lists parentList = App.BnBRepo.GetAList(SelectedList.ListId); // .5 seconds
BnBItem newBnBItem;
foreach (BirdsnBflysMaster bbf in bbfList) // .4 seconds
{
newBnBItem = new BnBItem(parentList, bbf, selectedLocation, newList, thisYearList.ListId);
newList.ListAll.Add(newBnBItem);
if (newBnBItem.ListTypeID == "Bird")
{
...
}
else
{
...
}
}
return newList;
}
So:
buildThisList
gets called when the SelectedList
property changes.buildThisList
calls buildBnBList
which is the time consuming process.buildBnBList
has nothing in it that is done asynchronously.StatusBarIsVisible
is bound to both IsVisible
and IsRunning
of the ActivityIndicator
.How can I code this so that executing buildBnBList
does not block the UI thread?
Upvotes: 2
Views: 1019
Reputation: 247153
Yes you a mixing blocking (.Result
) with async code which risks causing deadlocks. async void
should be avoided, unless in an even handler.
So then why not do just that?
Create an event and event handler.
public event EventHandler ListSelected = delegate { }
this should now allow you to create an event handler
private async void OnListSelected(object sender, EventArgs e) {
StatusBarIsVisibile = true;
ThisList = await buildBnBList(SelectedList, selectedLocation, thisYearList.ListId);
StatusBarIsVisibile = false;
ThisList.MainVM = this;
ThisList.BuildView();
PIShowListHeaderText = SelectedList.Title.Trim();
}
You would obviously subscribe to the event (early in the life-cycle of course)
this.ListSelected += OnListSelected;
and raise the event as needed
private ListItem selectedList;
public ListItem SelectedList {
get {
return selectedList;
}
set {
if (selectedList != value) {
var oldValue = selectedList;
selectedList = value;
OnListSelected(this, EventArgs.Empty);
}
}
}
Upvotes: 4