2010-11-28 3 views
1

У меня есть класс WorkQueue, просто обратите внимание на DoNext() пока что остальные в основном помощники. В принципе, WorkQueue - это всего лишь очередь WorkItems. DoNext() несет ответственность за «Запуск незавершенного рабочего процесса со свободным фоном». Также обратите внимание, что он установит свойство 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(); 
} 

Где UploadQueue является WorkQueue<string, UploadedImage>. На 1-й (только первый) DoNext(), WorkItem.Worker - null. Я знаю, потому что кнопка «Отменить», привязанная к WorkItem.CancelCommand, отключена. При отладке я обнаружил, что причина в том, что рабочий имеет значение 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(); 

но Whats проблема с этим внутри, почему работник устанавливается в нуль? Если его null, из предложения 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(); 
} 

если все рабочие заняты, эта функция возвращает нуль;

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() несколько раз в течение короткого периода времени, не будет ни один работник, который не занят, так что вы получите нулевой рабочий

Смежные вопросы