这是我想做的事情:
到目前为止,我每次创建一个新的线程时都会创建一个新的线程,但是这样的开销似乎太多了。
据我所知,我应该使用BackgroundWorker类,但我看到的示例似乎启动了后台工作程序,在主线程中继续使用非阻塞UI,并在完成时从BackgroundWorker更新UI - 就像我现在一样。
如何使工作线程在没有工作要做的时候继续运行和休眠?
答案 0 :(得分:1)
虽然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答案中描述的生产者/消费者。调度程序方法允许您在特定的 thead中排队工作。
答案 1 :(得分:0)
为什么不使用Task Parallel Library?
每当检测到KeyUp事件时创建一个新任务,让TPL担心创建新线程。由于它使用线程池,因此每次触发事件时都不会创建新线程。
答案 2 :(得分:0)
您遇到的问题称为生产者/消费者问题。您可以使用任何可用的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;
尝试使用任务模式库而不是手动启动线程。这是你的朋友。