這個問題可能以前曾以各種方式提出過,但這裏是我想要做的。我將擁有一個帶有多個選項卡的Windows窗體。每個選項卡將包含一個網格對象。對於用戶創建的每個選項卡/網格,我希望生成一個專用線程來填充該網格的內容並獲得不斷獲得的信息。任何人都可以提供一個如何安全地做到這一點的例子?基本線程問題
謝謝。
這個問題可能以前曾以各種方式提出過,但這裏是我想要做的。我將擁有一個帶有多個選項卡的Windows窗體。每個選項卡將包含一個網格對象。對於用戶創建的每個選項卡/網格,我希望生成一個專用線程來填充該網格的內容並獲得不斷獲得的信息。任何人都可以提供一個如何安全地做到這一點的例子?基本線程問題
謝謝。
的初始化標籤內(假設的WinForms,直到我看到其他):
Thread newThread = new Thread(() =>
{
// Get your data
dataGridView1.Invoke(new Action(() => { /* add data to the grid here */ });
});
newThread.Start();
這顯然是最簡單的例子。您也可以使用ThreadPool生成線程(這通常在服務器端應用程序中完成)。
如果您使用的是.NET 4.0,您也可以使用Task Parallel庫,它也可以提供幫助。
我對這種方法的關注將是線程的數量和每個人的工作量。 OP指定了「許多」選項卡 - 太多的標籤工作量過多可能導致顯着的抖動,這實際上會損害性能。 ThreadPool會管理這個,TPL會更好地管理它。 – Ragoczy 2010-09-03 12:43:55
@Ragoczy - 這就是爲什麼我提到這是最簡單的例子,OP應該檢查ThreadPool和TPL(如果它可用)。 – 2010-09-03 12:48:24
感謝您的意見。我懷疑任何用戶會同時打開超過3-5個標籤頁。這將是最多的。 – 2010-09-03 13:07:19
你應該有線程的陣列,能夠控制它們
List<Thread> tabs = new List<Thread>();
...
要添加一個新的,會是這樣:
tabs.Add(new Thread(new ThreadStart(TabRefreshHandler));
//Now starting:
tabs[tabs.Count - 1].Start();
而且最後,在TabRefreshHandler中,您應該檢查哪一個是調用線程號,並且您將知道應該刷新哪個選項卡!
你如何計劃通過列表控制線程(好奇心問題)? – 2010-09-03 12:44:11
它非常容易,如果你想停止Tab3更新,你應該停止在列表的第3個槽中的Thread,因爲它們應該在同一時間添加,這個想法是在列表中的線程號和標籤號碼。您也可以使用HashTable來存儲選項卡的名稱。我認爲這種方式會給你更多的控制更新 – 2010-09-03 12:52:40
我問的原因是線程之間有更好的信號傳輸方式,而不是簡單地使用原始線程對象來停止執行。 – 2010-09-03 13:00:39
您可以使用兩種基本方法。選擇一種在你的情況下最有意義的方法。通常情況下,沒有正確或錯誤的選擇。他們在許多情況下都可以同樣工作。各有其優點和缺點。奇怪的是,社區似乎經常忽略拉法。我不確定這是爲什麼。我最近偶然發現了this這個問題,其中大家都推薦了推送方法,儘管這是拉方法的完美情況(有一個可憐的靈魂對抗了牛羣,並被降低了投票並最終刪除了他的答案,只剩下我作爲唯一的反對者)。
推法
有工作線程的數據推到窗體。您將需要使用ISynchronizeInvoke.Invoke
方法來完成此操作。這樣做的好處是每個數據項到達後都會立即添加到網格中。缺點是您必須使用昂貴的封送處理操作,並且如果工作線程太快地獲取數據,UI可能會陷入困境。
void WorkerThread()
{
while (true)
{
object data = GetNewData();
yourForm.Invoke(
(Action)(() =>
{
// Add data to your grid here.
}));
}
}
拉法
有UI線程從工作線程拉取數據。您將讓工作線程將新數據項排入共享隊列,UI線程將定期將這些項出列。這樣做的好處是可以節制每個線程獨立執行的工作量。隊列是緩衝區,隨着CPU使用率的消退和流動,緩衝區將收縮並增長。它還將工作線程的邏輯與UI線程分離。缺點是如果你的UI線程輪詢得不夠快或者工作線程可能超出隊列。而且,當然,這些數據項不會實時顯示在您的網格上。但是,如果您設置的時間間隔足夠短,可能不會成爲您的問題。
private Queue<object> m_Data = new Queue<object>();
private void YourTimer_Tick(object sender, EventArgs args)
{
lock (m_Data)
{
while (m_Data.Count > 0)
{
object data = m_Data.Dequeue();
// Add data to your grid here.
}
}
}
void WorkerThread()
{
while (true)
{
object data = GetNewData();
lock (m_Data)
{
m_Data.Enqueue(data);
}
}
}
不錯的答案。根據我的經驗,拉式方法幾乎總是生產質量軟件的最佳方法。 – 2010-09-03 13:53:50
@丹:是的,它驚人的頻率被忽略了。我的理論是這是牛羣效應。一旦想法得到栽培並發展出臨界質量,它就會起飛,其他所有事情都會被忽略,並且不加以應有的注意。 – 2010-09-03 14:08:48
我們是說WinForms還是WPF? – Arcturus 2010-09-03 12:36:31
@Arcturus - WinForms – 2010-09-03 12:41:48
這是.Net 4還是早期版本? – Ragoczy 2010-09-03 12:47:30