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; }
}
But I have problem with doWork and workerCompleted. I get error:
Delegate 'Func' does not take 1 arguments
How can I fix this? How should I change parameters? Thanks
It seems you are missing the second generic parameter - Tout;
The following code should take care of it:
using System;
using System.Collections.Generic;
using System.ComponentModel;
public static class QueuedBackgroundWorker
{
public static void QueueWorkItem<Tin, Tout>(
Queue<QueueItem<Tin>> queue,
Tin inputArgument,
Func<DoWorkArgument<Tin>, Tout> doWork,
Action<WorkerResult<Tout>> 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>((Tin)args.Argument));
}
};
bw.RunWorkerCompleted += (sender, args) =>
{
if (workerCompleted != null)
{
workerCompleted(new WorkerResult<Tout>((Tout)args.Result, args.Error));
}
queue.Dequeue();
if (queue.Count > 0)
{
QueueItem<Tin> nextItem = queue.Peek(); // as QueueItem<T>;
nextItem.BackgroundWorker.RunWorkerAsync(nextItem.Argument);
}
};
queue.Enqueue(new QueueItem<Tin>(bw, inputArgument));
if (queue.Count == 1)
{
QueueItem<Tin> nextItem = queue.Peek() as QueueItem<Tin>;
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; }
}
And the usage should be:
private readonly Queue<QueueItem<int>> _workerQueue = new Queue<QueueItem<int>>();
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);
}
);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With