问题描述
我需要创建队列并将其与 BackgroundWorker 一起使用.所以我可以添加操作,下一个完成时在后台启动.我通过谷歌找到了这段代码:
I need to create queue and use it with BackgroundWorker. So I can add operations and when one is done next is starting in background. I found this code by google:
public class QueuedBackgroundWorker<T>
{
public void QueueWorkItem(
Queue queue,
T inputArgument,
Func<T> doWork,
Action workerCompleted)
{
if (queue == null) throw new ArgumentNullException("queue");
BackgroundWorker bw = new BackgroundWorker();
bw.WorkerReportsProgress = false;
bw.WorkerSupportsCancellation = false;
bw.DoWork += (sender, args) =>
{
if (doWork != null)
{
args.Result = doWork(new DoWorkArgument<T>((T)args.Argument));
}
};
bw.RunWorkerCompleted += (sender, args) =>
{
if (workerCompleted != null)
{
workerCompleted(new WorkerResult<T>((T)args.Result, args.Error));
}
queue.Dequeue();
if (queue.Count > 0)
{
QueueItem<T> nextItem = queue.Peek() as QueueItem<T>;
nextItem.BackgroundWorker.RunWorkerAsync(nextItem.Argument);
}
};
queue.Enqueue(new QueueItem<T>(bw, inputArgument));
if (queue.Count == 1)
{
QueueItem<T> nextItem = queue.Peek() as QueueItem<T>;
nextItem.BackgroundWorker.RunWorkerAsync(nextItem.Argument);
}
}
}
public class DoWorkArgument<T>
{
public DoWorkArgument(T argument)
{
this.Argument = argument;
}
public T Argument { get; private set; }
}
public class WorkerResult<T>
{
public WorkerResult(T result, Exception error)
{
this.Result = result;
this.Error = error;
}
public T Result { get; private set; }
public Exception Error { get; private set; }
}
public class QueueItem<T>
{
public QueueItem(BackgroundWorker backgroundWorker, T argument)
{
this.BackgroundWorker = backgroundWorker;
this.Argument = argument;
}
public T Argument { get; private set; }
public BackgroundWorker BackgroundWorker { get; private set; }
}
但我对 doWork 和 workerCompleted 有疑问.我得到错误:
But I have problem with doWork and workerCompleted. I get error:
Delegate 'Func' 不接受 1 个参数
Delegate 'Func' does not take 1 arguments
我该如何解决这个问题?我应该如何更改参数?谢谢
How can I fix this? How should I change parameters? Thanks
推荐答案
这是一个更短的方法,可以满足您的需求:
Here's a much shorter method that does what you want:
public class BackgroundQueue
{
private Task previousTask = Task.FromResult(true);
private object key = new object();
public Task QueueTask(Action action)
{
lock (key)
{
previousTask = previousTask.ContinueWith(t => action()
, CancellationToken.None
, TaskContinuationOptions.None
, TaskScheduler.Default);
return previousTask;
}
}
public Task<T> QueueTask<T>(Func<T> work)
{
lock (key)
{
var task = previousTask.ContinueWith(t => work()
, CancellationToken.None
, TaskContinuationOptions.None
, TaskScheduler.Default);
previousTask = task;
return task;
}
}
}
通过添加每个新动作作为前一个动作的延续,您可以确保一次只处理一个动作,因为在前一个项目完成之前下一个项目不会开始,您可以确保没有线程闲置无事可做时闲置,并确保它们都按顺序完成.
By adding each new action as a continuation of the previous you ensure that only one is worked on at a time, as the next item won't start until the previous item is finished, you ensure that there is no thread sitting around idling when there is nothing to be worked on, and you ensure they're all done in order.
另外请注意,如果您认为只需要一个队列而不是任何数量,您可以将所有成员设为 static
,但这取决于您.
Also note that if you only ever think you'll need one queue, and not any number, you could make all of the members static
, but that's up to you.
这篇关于使用队列创建 BackgroundWorker的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!