我有一个班级WorkQueue
,暂时注意DoNext()
,其余的主要是助手。基本上,WorkQueue
只是WorkItems
的队列。 DoNext()
负责“与自由后台工作者一起启动待处理的WorkItem”。另请注意,它将设置WorkItem.Worker
属性。
public class WorkQueue<Tin, Tout> :
INotifyCollectionChanged, IEnumerable<WorkItem<Tin, Tout>>
{
public bool DoNext()
{
// check if any work left in queue
WorkItem<Tin, Tout> item = GetWork();
if (item != null)
{
// check if any free workers
BackgroundWorker worker = GetWorker();
Debug.WriteLine(
"[WorkQueue.DoNext] Setting Worker to WorkItem: " + worker);
item.Worker = worker;
if (worker != null)
{
worker.RunWorkerAsync(item);
return true;
}
}
return false;
}
public void AddWork(WorkItem<Tin, Tout> item)
{
_queue.Add(item);
RaiseCollectionChanged(
new NotifyCollectionChangedEventArgs(
NotifyCollectionChangedAction.Add, item));
}
public WorkItem<Tin, Tout> GetWork()
{
return (from i in _queue
where i.Status == WorkStatus.Pending
select i).FirstOrDefault();;
}
public BackgroundWorker GetWorker()
{
return (from worker in _workers
where worker.IsBusy == false
select worker).FirstOrDefault();
}
}
我遇到的问题是当我做下面的事情时,
foreach (string filename in fileNames) {
UploadQueue.AddWork(new WorkItem<string, UploadedImage>(filename));
UploadQueue.DoNext();
}
UploadQueue
是WorkQueue<string, UploadedImage>
的位置。在1日(仅限第一个)DoNext()
,WorkItem.Worker
为空。我知道因为绑定到WorkItem.CancelCommand
的取消按钮被禁用了。在调试时,我发现原因是因为worker是null。
_cancelCommand = new RelayCommand(... () =>
{
// Returns true if WorkItem is being processed with a worker that supports
// cancellation or if the WorkItem is still Pending
// False if otherwise, eg. already completed, cancelled etc
if (Status == WorkStatus.Processing)
{
if (_worker != null && _worker.WorkerSupportsCancellation)
return true;
} else if (Status == WorkStatus.Pending) {
return true;
}
return false;
});
解决方案是将DoNext()
移出循环,
foreach (string filename in fileNames)
UploadQueue.AddWork(new WorkItem<string, UploadedImage>(filename));
UploadQueue.DoNext();
但是里面的问题是什么,为什么worker设置为null?如果为null,则从if子句开始,BackgroundWorker
不应该启动?
if (worker != null)
worker.RunWorkerAsync(item);
答案 0 :(得分:1)
public BackgroundWorker GetWorker()
{
return (from worker in _workers
where worker.IsBusy == false
select worker).FirstOrDefault();
}
如果所有工作人员都忙,则此函数将返回null;
foreach (string filename in fileNames)
UploadQueue.AddWork(new WorkItem<string, UploadedImage>(filename));
UploadQueue.DoNext();
UploadQueue.DoNext()多次执行
foreach (string filename in fileNames)
UploadQueue.AddWork(new WorkItem<string, UploadedImage>(filename));
UploadQueue.DoNext();
UploadQueue.DoNext()执行一次。
然后很明显,如果你在短时间内多次执行UploadQueue.DoNext(),就会没有工作人员不忙,所以你得到一个空工作者