2010-11-28 88 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()多次,就不會有工人是不是很忙,所以你得到一個空工人