我正在尝试在应用程序启动时启动一个线程,并等待UI在不使用BackgroundWorker的情况下为其提供一些工作。当没有给出任何工作时,该线程会休眠,当ui要求它执行某些操作时,该线程会被唤醒。
更多详情:
简单的WPF应用程序:我有一个StorageClass可以将文件复制到长期存储。该类是WPF应用程序的一部分。当用户单击按钮将文件存储到长期存储(低速阵列)时,我想要一个线程将此文件从高速存储阵列复制到长期存储。这些是大文件,我不希望UI被阻止。我想使用一个等待指令传输的线程。希望这能让我更清楚地了解我的目标。
答案 0 :(得分:2)
如果您使用的是.NET 4.0或更高版本,我建议直接使用TPL over threading,我建议使用BlockingCollection<T>
作为UI可以通过集合“提供一些工作”的方式供消费者使用。
然后,消费者可以是从Task
消耗的长期BlockingCollection<T>
(再次来自TPL),这样,您就不需要任何睡眠或手动工件,BlockingCollection<T>
允许您阻止等待一段时间,然后在项目准备好消耗后恢复。
因此,您可以将取消令牌源,阻止收集和任务定义为:
private BlockingCollection<Transaction> _bin = new BlockingCollection<Transaction>();
private CancellationTokenSource _tokenSource = new CancellationTokenSource();
private Task _consumer;
您的消费者方法可以定义为:
private void ConsumeTransactions()
{
// loop until consumer marked completed, or cancellation token set
while (!_bin.IsCompleted && !_tokenSource.Token.IsCancelRequested)
{
Transaction item;
// try to take item for 100 ms, or until cancelled
if (_bin.TryTake(out item, 100, _tokenSource.Token)
{
// consume the item
}
}
}
然后,您可以在表单加载时启动任务:
// when you have a task running for life of your program, make sure you
// use TaskCreationOptions.LongRunning. This typically sets up its own
// dedicated thread (not pooled) without having to deal with threads directly
_consumer = Task.Factory.StartNew(ConsumeTransactions, _tokenSource.Token,
TaskCreationOptions.LongRunning, TaskScheduler.Default);
然后通过执行以下操作添加项目:
_bin.TryAdd(someTransaction);
Transaction
只是您定义要执行的工作单元的任何内容......
然后,最后,当您的应用程序想要关闭时,它可以执行:
_bin.CompleteAdding();
告诉消费者不再有任何项目添加到队列中,这将使TryTake()
返回false
,并退出循环,因为_bin.IsCompleted
将true
1}}。
您的长时间运行任务可以循环阻塞获取,直到取消令牌(也是TPL)设置为告诉它关闭...