2010-02-20 44 views
2

我有一個文本過濾器,其中在TextChanged事件我推出一個ListView填入代碼這種方式在C#中的一個問題:使用線程和ListView

ThreadPool.QueueUserWorkItem(new WaitCallback(populate)); 
在填入方法

然後,我有這樣的

代碼
listView1.BeginUpdate(); 
listView1.Clear(); 

// rest of the code 

listView1.EndUpdate(); 

但listView1.BeginUpdate()調用給出了以下異常:

System.NotSupportedException was unhandled 
    Message="An error message cannot be displayed because an optional resource assembly containing it cannot be found" 
    StackTrace: 
    at Microsoft.AGL.Common.MISC.HandleAr() 
    at System.Windows.Forms.ListView.ntvSetStyleEx() 
    at System.Windows.Forms.ListView.BeginUpdate() 
    at App.frmSelectClient.populate() 
    at WorkItem.doWork() 
    at System.Threading.Timer.ring() 
    InnerException: 

我什麼DOI恩錯了嗎?

我想在後臺線程中發佈ListView的填充。

回答

5

您不能從UI線程以外的任何線程更新UI元素。使用Control.Invoke/BeginInvoke來執行此操作。

您可以在後臺線程中完成所有數據加載等,但您需要編組到UI線程以實際填充UI控件本身。

這是大多數UI框架 - 當然還有Windows窗體(桌面和CF)和Windows Presentation Foundation(使用Dispatcher而不是Control.Invoke/BeginInvoke)。

需要注意的一點:如果我沒有記錯,Compact Framework僅支持Control.Invoke/BeginInvoke的EventHandler委託。誠然,這在最近的版本中可能已經發生了變化。

+0

你可以請一個簡單的代碼片段來處理CF 2.0的調用? – Pentium10 2010-02-20 17:34:25

+2

CF 3.5允許任何代表。 2.0和1.0僅限於使用EventHandler – ctacke 2010-02-20 17:59:16

+0

@ Pentium10:查找有關Control.Invoke/BeginInvoke的任何教程,它將提供示例代碼。只要委託是EventHandler,它就可以在Compact Framework上正常工作。 – 2010-02-20 18:00:51

1

就像它在其他帖子中提到的從另一個線程更新ListView一樣,你必須用正確的方法使用BeginInvoke/Invoke。我爲自己創建了幾個線程安全的幫助器函數(對於ListView和更多控件)。每當我想用listview做一些事情或者控制自己時,我只是使用下面提到的那些。當然,它錯過了很多其他的選擇,但到目前爲止我還沒有其他的需要,所以我沒有創造更多,但它應該告訴你最終將它們添加到列表中的正確方法。

internal class GlobalFunctions { 
    public static void changeControlStatus(Control varControl, bool varState) { 
     if (varControl.InvokeRequired) { 
      varControl.BeginInvoke(new ControlStateChange(changeControlStatus), new object[] {varControl, varState}); 
     } else { 
      varControl.Enabled = varState; 
     } 
    } 
    public static void changeControlText(Control varControl, string varText) { 
     if (varControl.InvokeRequired) { 
      varControl.BeginInvoke(new ControlTextChange(changeControlText), new object[] {varControl, varText}); 
     } else { 
      varControl.Text = varText; 
     } 
    } 
    public static string readControlText(Control varControl) { 
     if (varControl.InvokeRequired) { 
      return (string) varControl.Invoke(new Func<String>(() => readControlText(varControl))); 
     } else { 
      string varText = varControl.Text; 
      return varText; 
     } 
    } 
    public static int listViewCountItems(ListView varControl) { 
     if (varControl.InvokeRequired) { 
      return (int) varControl.Invoke(new Func<int>(() => listViewCountItems(varControl))); 
     } else { 
      return varControl.Items.Count; 
      //string varText = varControl.Text; 
      //return varText; 
     } 
    } 
    public static void comboBoxClearItems(ComboBox varControl) { 
     if (varControl.InvokeRequired) { 
      varControl.BeginInvoke(new MethodInvoker(() => comboBoxClearItems(varControl))); 
     } else { 
      varControl.Items.Clear(); 
     } 
    } 
    public static void listViewClearItems(ListView varListView) { 
     if (varListView.InvokeRequired) { 
      varListView.BeginInvoke(new ListViewHandler(listViewClearItems), new object[] {varListView}); 
     } else { 
      varListView.Items.Clear(); 
     } 
    } 
    public static void listViewClearColumns(ListView varListView) { 
     if (varListView.InvokeRequired) { 
      varListView.BeginInvoke(new ListViewHandler(listViewClearColumns), new object[] {varListView}); 
     } else { 
      varListView.Clear(); 
     } 
    } 
    public static void listViewAddItem(ListView varListView, ListViewItem item) { 
     if (varListView.InvokeRequired) { 
      varListView.BeginInvoke(new MethodInvoker(() => listViewAddItem(varListView, item))); 
     } else { 
      varListView.Items.Add(item); 
     } 
    } 
    public static void listViewEditItem(ListView varListView, int varRow, int varColumn, string varText) { 
     if (varListView.InvokeRequired) { 
      varListView.BeginInvoke(new MethodInvoker(() => listViewEditItem(varListView, varRow,varColumn, varText))); 
     } else { 
      varListView.Items[varRow].SubItems[varColumn].Text = varText; 
     } 
    } 
    public static void listViewEditItemColor(ListView varListView, int varRow, Color varColor) { 
     if (varListView.InvokeRequired) { 
      varListView.BeginInvoke(new MethodInvoker(() => listViewEditItemColor(varListView, varRow, varColor))); 
     } else { 
      varListView.Items[varRow].BackColor = varColor; 
     } 
    } 
    public static void listViewChangeBackColor(ListView varListView, ListViewItem item, Color varColor) { 
     if (varListView.InvokeRequired) { 
      varListView.BeginInvoke(new MethodInvoker(() => listViewChangeBackColor(varListView, item, varColor))); 
     } else { 
      for (int i = 0; i < varListView.Columns.Count; i++) { 
       item.UseItemStyleForSubItems = false; 
       item.SubItems[i].BackColor = varColor; 
      } 
     } 
    } 
    public static void listViewChangeHeaderStyle(ListView varListView, ColumnHeaderStyle varColumnHeaderStyle) { 
     if (varListView.InvokeRequired) { 
      varListView.BeginInvoke(new MethodInvoker(() => listViewChangeHeaderStyle(varListView, varColumnHeaderStyle))); 
     } else { 
      varListView.HeaderStyle = varColumnHeaderStyle; 
     } 
    } 
    public static void listViewAddItemRange(ListView varListView, ListViewItem item) { 
     if (varListView.InvokeRequired) { 
      varListView.BeginInvoke(new MethodInvoker(() => listViewAddItemRange(varListView, item))); 
     } else { 
      //varListView.Items.Add(item); 
      varListView.Items.AddRange(new[] {item}); 
     } 
    } 
    public static void listViewAddColumn(ListView varListView, string varColumnName, int varColumnSize) { 
     if (varListView.InvokeRequired) { 
      varListView.BeginInvoke(new MethodInvoker(() => listViewAddColumn(varListView, varColumnName, varColumnSize))); 
     } else { 
      varListView.Columns.Add(varColumnName, varColumnSize, HorizontalAlignment.Left); 
     } 
    } 
    #region Nested type: ControlStateChange 
    private delegate void ControlStateChange(Control varControl, bool varState); 
    #endregion 
    #region Nested type: ControlTextChange 
    private delegate void ControlTextChange(Control varControl, string varText); 
    #endregion 
    private delegate string ControlTextRead(Control varControl); 
    #region Nested type: ListViewHandler 
    private delegate void ListViewHandler(ListView varListView); 
    #endregion 
    #region Nested type: ListViewHandlerItem 
    private delegate void ListViewHandlerItem(ListView varListView, ListViewItem item); 
    #endregion 
} 

用法很簡單:GlobalFunctions.listViewClearItems(yourListView);
希望這有助於:)

編輯:我錯過了緊湊的框架標籤,所以不知道這適用於它。有人應該能夠確認你。

+0

對於3.5這些將工作(雖然爲什麼不使用擴展方法大小寫?)。對於我認爲提問者正在使用的2.0,這些不會僅支持EventHandler。 – ctacke 2010-02-20 22:21:21

+0

我還沒有達到編程的水平:-)現在學習每一天,現在要閱讀關於擴展方法以及如何使用它們。照顧我的一個方法的例子嗎? – MadBoy 2010-02-20 22:49:08