J'ai une classe WorkQueue
, il suffit de prendre note sur le DoNext()
pour le moment, le reste sont principalement des aides. Fondamentalement, WorkQueue
est juste une file d'attente de WorkItems
. DoNext()
est responsable de "Démarrage d'un workItem en attente avec un travailleur en arrière-plan libre". Notez également qu'il définira la propriété WorkItem.Worker
.Besoin d'aide débogage pourquoi la propriété n'est pas définie/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();
}
}
Le problème que j'ai est quand je fais quelque chose comme ci-dessous,
foreach (string filename in fileNames) {
UploadQueue.AddWork(new WorkItem<string, UploadedImage>(filename));
UploadQueue.DoNext();
}
Où UploadQueue
est un WorkQueue<string, UploadedImage>
. Le 1er (premier seulement) DoNext()
, le WorkItem.Worker
est nul. Je le sais parce que mon bouton Annuler lié à WorkItem.CancelCommand
est désactivé. Lors du débogage, j'ai découvert que la raison en était que le worker est nul.
_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;
});
La solution est de déplacer le DoNext()
hors de la boucle,
foreach (string filename in fileNames)
UploadQueue.AddWork(new WorkItem<string, UploadedImage>(filename));
UploadQueue.DoNext();
mais ce qui est le problème avec l'intérieur, pourquoi est-travailleur défini sur null? Si son null, à partir de la clause if, le BackgroundWorker
ne devrait pas démarrer?
if (worker != null)
worker.RunWorkerAsync(item);
Video Demonstrating the Problem
ce n'est pas comment j'utiliser travailleurs de fond ... –
Quand la vérification de l'état du bouton est-elle effectuée? Et où s'inscrit _cancelCommand? – Doggett
Juste une suggestion, avez-vous pensé à utiliser des tâches à la place? –