[英]C# worker thread with event driven work and no shut down
這是我想做的事情:
到目前為止,每當有一個keyup時,我就一直在創建一個新線程,但是這種方式似乎有太多開銷。
據我所知,我應該使用BackgroundWorker類,但是我所看到的示例似乎是在啟動后台工作程序,在主線程中繼續非阻塞UI,並在完成后從BackgroundWorker中更新UI-即和我已經在做的一樣。
在沒有工作要做的情況下,如何使工作線程保持運行和睡眠?
盡管Zaches的答案是完全有效的(並且我使用了一段時間),但我偶然發現了我認為使用Dispatcher
一種更優雅的解決方案:
創建工作線程:
Dispatcher _workerDispatcher;
Thread _workerThread = new Thread(new ThreadStart(() =>
{
_workerDispatcher = Dispatcher.CurrentDispatcher; // Required to create the dispatcher
Dispatcher.Run(); // Keeps thread alive and creates a queue for work
});
_workerThread.Start();
將工作放入輔助線程(從主線程或其他線程):
// Synchronous work
_workerDispatcher.Invoke(() =>
{
// Do stuff
});
// Asynchronous work (makes most sense for background work)
_workerDispatcher.BeginInvoke(() =>
{
// Do stuff
});
關閉工作線程:
_workerDispatcher.InvokeShutdown();
_workerThread.Join(); // Wait for thread to shut down
我正在使用new Thread()
因為我需要設置單元狀態,但是您也可以使用使用Task.Run()
和Task.Factory.StartNew()
創建的任務。
我不是100%肯定有必要調用thread.Join()
,但我想確定線程已關閉。 如果您使用的是Task
調用task.Wait()
。
獲得另一種方式Dispatcher
是調用Dispatcher.FromThread(thread)
,但要注意,這是很重要的Dispatcher
不創建直到CurrentDispatcher
已使用(即使你不使用后的參考)。
這種方法的缺點是不能使多個線程從隊列中選擇項目並進行工作-為此,您將不得不使用Zaches答案中描述的生產者/消費者方法。 調度程序方法使您可以將特定隊列中的工作排隊。
您為什么不只使用任務並行庫 ?
每當您檢測到KeyUp事件時就創建一個新任務,並讓TPL擔心創建新線程。 由於它使用線程池,因此不會在每次觸發事件時創建新線程。
您遇到的問題稱為生產者/消費者問題。 您可以使用任何可用的ConcurrentCollections輕松解決它。
嘗試這樣的事情:
var queue = new ConcurrentQueue<string>();
var consume = true;
var producer = Task.Run(() =>
{
var input = Console.ReadLine();
while(!string.IsNullOrEmpty(input)
{
queue.Enqueue(input);
input = Console.ReadLine();
}
});
var consumer = Task.Run(() =>
{
while(consume) //So we can stop the consumer
{
while(!queue.IsEmpty) //So we empty the queue before stopping
{
stringres;
if(queue.TryDequeue(out res)) Console.WriteLine(res);
}
}
});
await producer;
consume = false;
await consumer;
嘗試使用任務模式庫,而不是手動啟動線程。 是你的朋友。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.