2010-11-28 64 views
1

我有一个类WorkQueue,现在就注意一下DoNext(),其余的主要是帮手。基本上,WorkQueue只是一个队列WorkItemsDoNext()负责“使用免费的后台工作人员开始挂起的工作项目”。另请注意,它将设置WorkItem.Worker属性。需要帮助调试为什么没有设置属性/ null

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(); 
} 

UploadQueueWorkQueue<string, UploadedImage>。在第一天(第一次)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(); 

但什么的问题,这里面,为什么工人设置为空?如果if从if子句开始为空,BackgroundWorker不应该启动?

if (worker != null) 
    worker.RunWorkerAsync(item); 

Video Demonstrating the Problem

+0

这不是我会怎么用后台工作人员...... – 2010-11-28 15:43:06

回答

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()多次,就不会有工人是不是很忙,所以你得到一个空工人