2010-11-28 10 views
1

Ich habe eine Klasse WorkQueue, nur zur Kenntnis nehmen über die DoNext() für jetzt, der Rest sind hauptsächlich Helfer. Grundsätzlich ist WorkQueue nur eine Warteschlange von WorkItems. DoNext() ist verantwortlich für "Starten eines ausstehenden Arbeitselements mit einem freien Hintergrund Worker". Beachten Sie auch, dass die Eigenschaft WorkItem.Worker festgelegt wird.Brauchen Sie Hilfe Debuggen, warum Eigenschaft nicht gesetzt ist/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(); 
    } 
} 

Das Problem, das ich habe, ist, wenn ich etwas tun, wie unten,

foreach (string filename in fileNames) { 
    UploadQueue.AddWork(new WorkItem<string, UploadedImage>(filename)); 
    UploadQueue.DoNext(); 
} 

Wo UploadQueue ein WorkQueue<string, UploadedImage> ist. Auf der ersten (nur ersten) DoNext() ist die WorkItem.Worker Null. Ich weiß das, weil meine Abbrechen-Schaltfläche, die an WorkItem.CancelCommand gebunden ist, deaktiviert ist. Beim Debugging stellte ich fest, dass der Grund darin lag, dass der Worker null ist.

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

Die Lösung ist die DoNext() aus der Schleife zu bewegen,

foreach (string filename in fileNames) 
    UploadQueue.AddWork(new WorkItem<string, UploadedImage>(filename)); 
UploadQueue.DoNext(); 

aber was ist das Problem mit ihm nach innen, warum Arbeiter auf null gesetzt wird? Wenn sein Null, von der if-Klausel, sollte die BackgroundWorker nicht starten?

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

Video Demonstrating the Problem

+0

bekommen, die nicht ist, wie ich verwenden würde Hintergrund Arbeiter ... –

+1

Wann ist die Prüfung für den Button Status? Und wo passt der _cancelCommand? – Doggett

+0

Nur ein Vorschlag, haben Sie daran gedacht, stattdessen Aufgaben zu verwenden? –

Antwort

1
public BackgroundWorker GetWorker() 
{ 
    return (from worker in _workers 
      where worker.IsBusy == false 
      select worker).FirstOrDefault(); 
} 

wenn alle Arbeiter beschäftigt sind, wird diese Funktion null zurück;

foreach (string filename in fileNames) 
    UploadQueue.AddWork(new WorkItem<string, UploadedImage>(filename)); 
    UploadQueue.DoNext(); 

UploadQueue.DoNext() ausgeführt mehrfach

foreach (string filename in fileNames) 
    UploadQueue.AddWork(new WorkItem<string, UploadedImage>(filename)); 
UploadQueue.DoNext(); 

UploadQueue.DoNext() einmal ausgeführt.

Dann ist es ganz klar, wenn man UploadQueue.DoNext() mehrere Male in einer kurzen Zeitperiode ausführen, wird es keine Arbeiter, die nicht besetzt ist, so dass Sie einen Null-Arbeiter