簡體   English   中英

有一個無盡的工人線程的正確方法?

[英]Proper way to have an endless worker thread?

我有一個需要大量初始化的對象(在一台強壯的機器上1-2秒)。 雖然一旦初始化,只需要大約20毫秒來做一個典型的“工作”

為了防止每次應用程序想要使用它時重新初始化它(可能是每秒50次,或者在典型使用中幾分鍾都沒有),我決定給它一個工作,並讓它運行在它自己的線程上,檢查在que中是否有任何工作。 但是,我不完全確定如何創建一個無論是否有工作運行的線程。

這就是我到目前為止所做的任何批評都受到歡迎

    private void DoWork()
    {
        while (true)
        {
            if (JobQue.Count > 0)
            {
                // do work on JobQue.Dequeue()
            }
            else
            {
                System.Threading.Thread.Sleep(50);
            }
        }
    }

經過深思熟慮:我以為我可能需要優先殺死這個線程讓它永遠運行,所以我想我會添加一個告訴線程結束的Job類型。 關於如何結束這樣的線程的任何想法也贊賞。

無論如何你需要 lock ,所以你可以WaitPulse

while(true) {
    SomeType item;
    lock(queue) {
        while(queue.Count == 0) {
            Monitor.Wait(queue); // releases lock, waits for a Pulse,
                                 // and re-acquires the lock
        }
        item = queue.Dequeue(); // we have the lock, and there's data
    }
    // process item **outside** of the lock
}

添加像:

lock(queue) {
    queue.Enqueue(item);
    // if the queue was empty, the worker may be waiting - wake it up
    if(queue.Count == 1) { Monitor.PulseAll(queue); }
}

您可能還想查看這個問題 ,這會限制隊列的大小(如果它太滿則會阻塞)。

您需要一個同步原語,如WaitHandle (查看靜態方法)。 通過這種方式,您可以“發出信號”工作線程有效。 它會檢查隊列並繼續工作,直到隊列為空,此時它會等待互斥鎖再次發出信號。

使其中一個作業項也是一個退出命令,這樣你可以在退出線程時發出工作線程的信號

在大多數情況下,我這樣做與您的設置非常相似 - 但不是使用相同的語言。 我有一個使用數據結構(在Python中)的優勢,它將阻塞線程直到項目被放入隊列,從而無需進行睡眠調用。

如果.NET提供了類似的類,我會考慮使用它。 線程阻塞比在睡眠調用上旋轉的線程要好得多。

你可以傳遞的工作可以像“null”一樣簡單; 如果代碼收到一個null,它知道是時候突破並回家了。

抓住並行框架 它有一個BlockingCollection <T> ,您可以將其用作作業隊列。 你如何使用它是:

  1. 創建將保存任務/作業的BlockingCollection <T>。
  2. 創建一些具有永無止境循環的線程(while(true){//從隊列中獲取作業)
  3. 設置線程
  4. 當作業可用時,將作業添加到集合中

線程將被阻塞,直到項目出現在集合中。 無論誰轉過它都會得到它(取決於CPU)。 我現在正在使用它,效果很好。

它還具有依賴於MS來編寫特別討厭的代碼的優點,其中多個線程訪問相同的資源。 無論什么時候你都可以讓其他人寫下你應該去的。 當然,假設他們擁有比您更多的技術/測試資源和綜合經驗。

如果你真的不需要讓線程退出(並且只是希望它不讓你的應用程序繼續運行),你可以將Thread.IsBackground設置為true,它將在所有非后台線程結束時結束。 Will和Marc都有很好的解決方案來處理隊列。

我已經實現了一個后台任務隊列,而不使用任何類型的while循環,或者脈沖,或者等待,或者實際上完全觸及Thread對象。 它似乎工作。 (我的意思是它在生產環境中處理了過去18個月中每天數千個任務而沒有任何意外行為。)這是一個具有兩個重要屬性的類, Queue<Task>BackgroundWorker 有三種重要方法,縮寫如下:

private void BackgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
   if (TaskQueue.Count > 0)
   {
      TaskQueue[0].Execute();
   }
}

private void BackgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    Task t = TaskQueue[0];

    lock (TaskQueue)
    {
        TaskQueue.Remove(t);
    }
    if (TaskQueue.Count > 0 && !BackgroundWorker.IsBusy)
    {
        BackgroundWorker.RunWorkerAsync();
    }
}

public void Enqueue(Task t)
{
   lock (TaskQueue)
   {
      TaskQueue.Add(t);
   }
   if (!BackgroundWorker.IsBusy)
   {
      BackgroundWorker.RunWorkerAsync();
   }
}

並不是沒有等待和脈動。 但這一切都發生在BackgroundWorker 只要在隊列中刪除任務,運行直到隊列為空,然后返回休眠狀態,這就會喚醒。

我不是線程專家。 如果使用BackgroundWorker會有這樣的問題,是否有理由搞亂System.Threading

暫無
暫無

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

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