【问题标题】:ObservableQueue empty when trying to dequeue尝试出队时 ObservableQueue 为空
【发布时间】:2019-09-30 02:54:02
【问题描述】:

我已经以这种方式实现了自己的 ObservableQueue:

public class ObservableQueue<T> : Queue<T>, INotifyPropertyChanged, INotifyCollectionChanged
    {
        public event NotifyCollectionChangedEventHandler CollectionChanged;
        public event PropertyChangedEventHandler PropertyChanged;

        public ObservableQueue() : base() { }
        public ObservableQueue(IEnumerable<T> collection) : base(collection) { }
        public ObservableQueue(int capacity) : base(capacity) { }

        public virtual new T Enqueue(T item)
        {
            lock (this)
            {
                base.Enqueue(item);
            }
            OnCollectionChanged(NotifyCollectionChangedAction.Add, item);

            return item;
        }

        public virtual new T Dequeue()
        {
            lock (this)
            {
                var item = base.Dequeue();
                return item;
            }
        }

        protected virtual void OnCollectionChanged(NotifyCollectionChangedAction action, T item)
        {
            CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(
                action
                , item
                , item == null ? -1 : 0)
            );

            OnPropertyChanged(nameof(Count));
        }

        protected virtual void OnPropertyChanged(string proertyName)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(proertyName));
        }
    }

我订阅了 MainWindow 中的队列:

paths.CollectionChanged += Process;

当一个文件被添加到一个特定的文件夹时,我排队:

private void FileCreated(Object sender, FileSystemEventArgs e)
      {
          try
           {
                paths.Enqueue(currentPath);
           } catch (InvalidOperationException exception)
           {
               string messageBoxText = exception.Message;
               MessageBoxButton button = MessageBoxButton.OK;
               System.Windows.MessageBox.Show(messageBoxText, "Error", button);
          } 
       }

这会触发队列上的 CollectionChanged,我在其中运行它:

private async void Process(object sender, NotifyCollectionChangedEventArgs e)
        {

            var currentPath = paths.Dequeue();
            await UploadFile(currentPath);
            Thread.Sleep(5000);
            try
            {
                 MoveFile(currentPath, outputFolderPath, System.IO.Path.GetFileName(currentPath));
             } catch (IOException IOE)
            {
                 Console.WriteLine(IOE.StackTrace);
            }
       }

但我在尝试出队时收到以下错误:

System.InvalidOperationException: '队列为空。'

我似乎无法弄清楚队列怎么可能是空的?

我偶尔也会遇到以下异常:

异常信息:System.InvalidOperationException 在 System.ThrowHelper.ThrowInvalidOperationException(System.ExceptionResource) 在 System.Collections.Generic.Queue1[[System.__Canon, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]].Dequeue() at Program.Utilities.ObservableQueue1[[System.__Canon,mscorlib, 版本=4.0.0.0,文化=中性, PublicKeyToken=b77a5c561934e089]].Dequeue() 在 Program.MainWindow+d__11.MoveNext() 在 System.Runtime.CompilerServices.AsyncMethodBuilderCore+c.b__6_1(System.Object) 在 System.Threading.QueueUserWorkItemCallback.WaitCallback_Context(System.Object) 在 System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, System.Threading.ContextCallback,System.Object,布尔值)在 System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback,System.Object,布尔值)在 System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem() 在 System.Threading.ThreadPoolWorkQueue.Dispatch() 在 System.Threading._ThreadPoolWaitCallback.PerformWaitCallback()

【问题讨论】:

  • 会不会是事件处理器被注册了多次?只有第一个调用才能出队。
  • 如果没有可靠地重现问题的良好minimal reproducible example,就不可能提供好的答案。也就是说:恕我直言,您应该通过继承ObservableCollection&lt;T&gt; 而不是Queue&lt;T&gt; 来实现您的ObservableQueue&lt;T&gt;。在现有的可观察集合类型上实现队列语义比在现有队列类型上实现集合更改语义要容易得多。
  • 我尝试添加更多代码,但遇到了一个新异常。

标签: c# wpf queue


【解决方案1】:

您的代码示例不完整,因为我们没有看到还有什么您对队列做了什么,所以我只是在这里猜测。是不是您使用“async void”作为附加的事件处理程序使 Process() 在您不断改变队列时异步运行,从而使此代码在线程池认为合适时以高度不确定的方式交错?

【讨论】:

  • 我没有对队列做任何其他事情,我添加了另一个我偶尔收到的异常。我认为您可能是对的,我该如何解决?我使用 async 来等待上传。
猜你喜欢
  • 1970-01-01
  • 2020-12-04
  • 2011-06-28
  • 2018-11-07
  • 1970-01-01
  • 1970-01-01
  • 2021-04-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多