使用队列创建BackgroundWorker

我需要创建队列并将其与BackgroundWorker一起使用。 所以我可以添加操作,然后在下一步完成时将在后台启动。 我通过谷歌找到了这个代码:

public class QueuedBackgroundWorker { public void QueueWorkItem( Queue queue, T inputArgument, Func 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)args.Argument)); } }; bw.RunWorkerCompleted += (sender, args) => { if (workerCompleted != null) { workerCompleted(new WorkerResult((T)args.Result, args.Error)); } queue.Dequeue(); if (queue.Count > 0) { QueueItem nextItem = queue.Peek() as QueueItem; nextItem.BackgroundWorker.RunWorkerAsync(nextItem.Argument); } }; queue.Enqueue(new QueueItem(bw, inputArgument)); if (queue.Count == 1) { QueueItem nextItem = queue.Peek() as QueueItem; nextItem.BackgroundWorker.RunWorkerAsync(nextItem.Argument); } } } public class DoWorkArgument { public DoWorkArgument(T argument) { this.Argument = argument; } public T Argument { get; private set; } } public class WorkerResult { 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 { 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的问题。 我收到错误:

委托’Func’不带1个参数

我怎样才能解决这个问题? 我该如何更改参数? 谢谢

这是一个更短的方法,可以满足您的需求:

 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 QueueTask(Func work) { lock (key) { var task = previousTask.ContinueWith(t => work() , CancellationToken.None , TaskContinuationOptions.None , TaskScheduler.Default); previousTask = task; return task; } } } 

通过添加每个新操作作为前一个的延续,您确保一次只处理一个,因为下一个项目在上一个项目完成之前不会启动,您确保在那里没有任何线程坐在空闲处没有什么可以解决的,你确保他们都按顺序完成。

另请注意,如果您认为自己只需要一个队列而不需要任何数字,那么您可以将所有成员设置为static ,但这取决于您。

看来你缺少第二个通用参数 – Tout;

以下代码应该处理它:

 using System; using System.Collections.Generic; using System.ComponentModel; public static class QueuedBackgroundWorker { public static void QueueWorkItem( Queue> queue, Tin inputArgument, Func, Tout> 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((Tin)args.Argument)); } }; bw.RunWorkerCompleted += (sender, args) => { if (workerCompleted != null) { workerCompleted(new WorkerResult((Tout)args.Result, args.Error)); } queue.Dequeue(); if (queue.Count > 0) { QueueItem nextItem = queue.Peek(); // as QueueItem; nextItem.BackgroundWorker.RunWorkerAsync(nextItem.Argument); } }; queue.Enqueue(new QueueItem(bw, inputArgument)); if (queue.Count == 1) { QueueItem nextItem = queue.Peek() as QueueItem; nextItem.BackgroundWorker.RunWorkerAsync(nextItem.Argument); } } } public class DoWorkArgument { public DoWorkArgument(T argument) { this.Argument = argument; } public T Argument { get; private set; } } public class WorkerResult { 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 { public QueueItem(BackgroundWorker backgroundWorker, T argument) { this.BackgroundWorker = backgroundWorker; this.Argument = argument; } public T Argument { get; private set; } public BackgroundWorker BackgroundWorker { get; private set; } } 

用法应该是:

  private readonly Queue> _workerQueue = new Queue>(); private int _workerId = 1; [Test] public void BackgroundTest() { QueuedBackgroundWorker.QueueWorkItem( this._workerQueue, this._workerId++, args => // DoWork { var currentTaskId = args.Argument; var now = DateTime.Now.ToLongTimeString(); var message = string.Format("DoWork thread started at '{0}': Task Number={1}", now, currentTaskId); return new { WorkerId = currentTaskId, Message = message }; }, args => // RunWorkerCompleted { var currentWorkerId = args.Result.WorkerId; var msg = args.Result.Message; var now = DateTime.Now.ToShortTimeString(); var completeMessage = string.Format( "RunWorkerCompleted completed at '{0}'; for Task Number={1}, DoWork Message={2}", now, currentWorkerId, msg); } ); }