2017-09-05 9 views
1

ListViewアイテムが選択されたときに実行されるコードがあります。このコードは実行にかなりの時間がかかりますので、実行中にActivityIndicatorを表示します。XAMarinフォームActivityIndi​​catorを表示するためにasync/awaitを正しく使用する方法

私はActivityIndicatorについてたくさんの投稿を読んでおり、正しく設定していると思います。 UIのスレッドがプロセス中に完全にフリーズしているため、実行中のコードがUIスレッドをブロックしていることが原因で問題が発生している可能性があります。

私はasyncを使用して見つけることができたすべてのバリエーションを経験しました/運がないのを待っているので、私はまだ間違ったことをやっていると仮定しています。だから、

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; 
} 

  • buildThisListをするときSelectedListプロパティの変更呼び出さ

    は、ここに私のコードです。

  • buildThisListbuildBnBListという時間がかかります。
  • buildBnBListには、非同期的に行われるものは何もありません。
  • StatusBarIsVisibleは、ActivityIndicatorIsVisibleIsRunningの両方に結合しています。

buildBnBListの実行でUIスレッドがブロックされないようにするにはどうすればよいですか?

答えて

3

はい、デッドロックの原因となる非同期コード付きのブロック(.Result)です。 async voidは、偶数ハンドラでない限り避けるべきです。

それでは、どうしてそうしないのですか?

イベントとイベントハンドラを作成します。

public event EventHandler ListSelected = delegate { } 

これは、今あなたが明らかに(早期もちろんのライフサイクルに)イベントを購読するでしょうあなたは、イベントハンドラ

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(); 
} 

を作成できるようにする必要があり

this.ListSelected += OnListSelected; 

必要に応じてイベントを開催する

private ListItem selectedList; 
public ListItem SelectedList { 
    get { 
     return selectedList; 
    } 
    set { 
     if (selectedList != value) { 
      var oldValue = selectedList; 
      selectedList = value; 
      OnListSelected(this, EventArgs.Empty); 
     } 
    } 
} 
+0

入力していただきありがとうございます。私はあなたが提案したことを理解していると思います。コードで実装しましたが、違いはありません。実行する前にStatusBarIsVisibile = trueに設定すると、ActivityIndi​​catorが回転しています。リストアイテムをクリックすると、スピナーが停止し、OnListSelectedが終了するまでUI内で何も起こりません。その時点でActivityIndi​​catorが再び回転を開始し、選択したアイテムiがハイライト表示されます。 – DaveS

関連する問題