簡體   English   中英

如果線程沒有修改該元素,是否可以從另一個線程訪問UI元素?

[英]Is it possible to access a UI element from another thread if the thread doesn't modify that element?

假設在實例化表單/ control / element(通常是主線程)的線程中運行的代碼不會同時修改/訪問該元素,是否可以:

  1. 獲取TextBox的Text屬性。

  2. 枚舉ListView。

  3. 訂閱Form的Closing事件。 (知道將從實例化該表單的線程調用鈎子)

我已經嘗試了所有3並且程序似乎沒有抱怨它。 我一直認為你必須調用任何想要遠程觸摸任何UI相關(讀或寫)的調用。

我非常清楚為什么在修改元素時需要使用IsInvokeRequired / Invoke模式,但我不明白為什么訪問屬性/事件會導致任何問題。

但這絕對有可能導致意外行為。 此外,還需要考慮其他與線程相關的錯誤,例如競爭條件/死鎖,請參閱托管線程最佳實踐

我總是堅持訪問UI線程上的UI以保證安全。

你正在做什么來確保UI線程在你讀取它時沒有修改控件? 編組到UI線程的全部原因是您不必擔心這種情況。 特別是枚舉列表框將是最容易打破的,因為它將花費最長的時間(這為競爭條件創建了最大的窗口)。 你應該為所有這3個事情的UI線程編組。

這不安全。 當您從另一個線程讀取控件時,UI線程可以(也可能會)更改控件的狀態。 您的讀取可能會在半生不熟的狀態下捕獲控件。 它似乎現在可以正常工作,但遲早它會失敗......可能是不可預測的和驚人的。

不,您可能不需要使用Invoke模式。 坦率地說......這種模式通常是最糟糕的選擇。 通常最好讓您的工作線程執行繁重的工作,然后通過隊列將新數據或進度信息發送到UI線程,並讓UI線程通過計時器選擇它。 這有幾個優點。

  • 消除昂貴的InvokeBeginInvoke操作。
  • UI線程決定用新數據更新自己的時間和頻率,而不是讓工作線程指示這一點。
  • 您可以在工作線程上獲得更多吞吐量,因為它不必等待Invoke返回。
  • BeginInvoke一樣,不存在超出UI消息隊列的風險。
  • 它解耦UI和工作線程交互。

您需要枚舉ListView並構建一個單獨的數據結構,然后工作線程可以安全地訪問它。 如果ListView包含許多項目,請考慮與控件一起維護單獨的集合。 這樣你就可以在更長的時間內分散處理數據的懲罰,因為它可能不會被注意到。 畢竟,我們不希望復制操作凍結UI線程,否則用戶會注意到。 ConcurrentBag等可能是一個不錯的選擇,因為當工作線程正在讀取它時,UI線程可以安全地修改它。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM