需要帮助调试为什么不设置属性/ null

时间:2010-11-28 15:21:31

标签: c# backgroundworker

我有一个班级WorkQueue,暂时注意DoNext(),其余的主要是助手。基本上,WorkQueue只是WorkItems的队列。 DoNext()负责“与自由后台工作者一起启动待处理的WorkItem”。另请注意,它将设置WorkItem.Worker属性。

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>的位置。在1日(仅限第一个)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();

但是里面的问题是什么,为什么worker设置为null?如果为null,则从if子句开始,BackgroundWorker不应该启动?

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

Video Demonstrating the Problem

1 个答案:

答案 0 :(得分: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(),就会没有工作人员不忙,所以你得到一个空工作者