3

私は人口のために次のコードをバックグラウンドスレッドからリストビュー(DoWorkがPopulateThreadメソッドを呼び出します)している:...どのような方法には、BackgroundWorkerを使用してフリーズすることなくUIを更新しますか?

delegate void PopulateThreadCallBack(DoWorkEventArgs e); 
private void PopulateThread(DoWorkEventArgs e) 
{ 

    if (this.InvokeRequired) 
    { 
     PopulateThreadCallBack d = new PopulateThreadCallBack(this.PopulateThread); 
     this.Invoke(d, new object[] { e }); 
    } 
    else 
    { 

     // Ensure there is some data 
     if (this.DataCollection == null) 
     { 
      return; 
     } 

     this.Hide(); 

     // Filter the collection based on the filters 
     List<ServiceCallEntity> resultCollection = this.ApplyFilter(); 

     // Get the current Ids 
     List<Guid> previousIdList = this.GetUniqueIdList(listView); 
     List<Guid> usedIdList = new List<Guid>(); 

     foreach (ServiceCallEntity record in resultCollection) 
     { 

      if (e.Cancel) 
      { 
       this.Show(); 
       return; 
      } 
      else 
      { 

       // Get the top level entities 
       UserEntity userEntity = IvdSession.Instance.Collection.GetEngineerEntity(record.UserId); 
       AssetEntity assetEntity = IvdSession.Instance.Collection.GetAssetEntity(record.AssetId); 
       SiteEntity siteEntity = IvdSession.Instance.Collection.GetSiteEntity(record.SiteId); 
       FaultEntity faultEntity = IvdSession.Instance.Collection.GetFaultEntity(record.FaultId); 

       if (siteEntity == null || userEntity == null || faultEntity == null) 
       { 
        continue; 
       } 
       else 
       { 

        // Get the linked entities 
        RegionEntity regionEntity = IvdSession.Instance.Collection.GetRegionEntity(siteEntity.RegionId); 
        StatusEntity statusEntity = IvdSession.Instance.Collection.GetStatusEntity(record.ServiceCallStatus.StatusId); 

        ListViewItem item = new ListViewItem(siteEntity.SiteName); 
        item.SubItems.Add(siteEntity.Address); 
        item.Tag = record; 

        item.SubItems.Add(regionEntity.Description); 

        // Handle if an Asset is involved 
        if (record.AssetId > 0) 
         item.SubItems.Add(assetEntity.AssetDisplay); 
        else 
         item.SubItems.Add("N/A"); 

        item.SubItems.Add(faultEntity.Description); 
        item.SubItems.Add(userEntity.UserDisplay); 

        item.SubItems.Add("TODO: Claimed By"); 
        item.SubItems.Add(record.DateTimeStamp.ToString()); 

        IvdColourHelper.SetListViewItemColour(item, false); 
        this.PopulateItem(item, ref usedIdList); 

       } 

      } 

     } 

     // Clean up the grid 
     this.CleanListView(previousIdList, usedIdList); 

     // Only autosize when allowed and when there are some items in the ListView 
     if (this.AllowAutoSize && listView.Items.Count > 0) 
     { 
      rsListView.AutoSizeColumns(listView); 
      this.AllowAutoSize = false; 
     } 

     this.Show(); 

    } 

} 

は残念ながら、これはforeachの中にいる間凍結するUIを引き起こしていますメインUIをフリーズせずにListViewを更新/設定しますか?

+0

だあなたはMethodInvoker

if(this.InvokeRequired) { this.BeginInvoke(new MethodInvoker(() => PopulateThread(e))); return; } 

を使用することができ、独自のデリゲートを定義する必要はありません - これは私が何であったかやって周りに完全に間違った方法であります達成しようとしている。このコードは以来、裸で修正されています。受け入れられた答えはボギーです。 – GenericTypeTea

答えて

11

A)おそらくthis.Invokeを使用してthis.BeginInvokeを使用する必要はありません。 Invokeは現在のスレッドをブロックします。

B)あなたはそれだけで追加するために非常にクリーン:)

+0

ありがとう、私はいくつかの改善を行います。 – GenericTypeTea

0

ポンプあなたは、このコードはまったくマルチスレッド化されていないという意味、ちょうど約すべてを実行するためにControl.Invokeを使用している

Application.DoEvents(); 
+0

パーフェクト、速い答えに感謝します! – GenericTypeTea

+5

-1、申し訳ありませんが、BgWorker-> Invoke-> DoEventsですか? 1つの穴に別の穴を当てるように見えます。 –

+1

良い点ですが、私は言うつもりですが、計算集約型のタスクでは敏感なGUIがあれば、複数のスレッドではなくApplication.DoEventsでかなり遠くまで到達できます。この機械の多くは、(実際にスレッドが本当に必要な場合を除いて)わずかな複雑さに過ぎません。たとえば、複数のスレッドでは、デバッグ+例外= FAILです。しかし、あなたの答えで言ったように、これはマルチスレッドコードではありません。命令型言語の並行性はPITAです。あなたが本当にそれを必要としない限り離れてください。 –

5

と手動でのイベント。

適切な方法(Backgroundworkerを含む)は、UpdateProgressイベントを使用して要素を追加することです。すでに同期されています。

しかし、このプロセス中にコントロールを隠しているので、リストを作成して完了したら、それをListviewに追加することもできます。そのコードは長くかかりません。

または何らかの組み合わせで、更新イベントで小さなリストを追加します。私はHide/Showの知恵について疑問を抱いていますが、UIをちらつかせるだけでいいと思います。それらを放置するか、SuspendLayout/Resumelayoutに置き換えます。

+1

リストにSortComparerが割り当てられている場合は、追加/削除がさらに遅くなることを追加する必要があります。変更を加えるときは、並べ替えを一時的に無効にしてから、すべての追加と削除が完了したら再度有効にすることをお勧めします。 –

関連する問題