Проблема с многопоточностью при перемещении файлов из одной папки в другую с помощью FileSystemWatcher - PullRequest
0 голосов
/ 26 сентября 2019

Я создал приложение, которое должно читать файлы при добавлении в папку, что-то делать с файлами и затем перемещать их в другую папку.Когда они доходят до точки их перемещения, я иногда получаю следующую ошибку, а иногда она работает гладко:

Процесс был прерван из-за необработанного исключения.Информация об исключении: System.IO.IOException в System.IO .__ Error.WinIOError (Int32, System.String) в System.IO .__ Error.WinIOError () в System.IO.File.InternalMove (System.String, System.String,Boolean) в System.IO.File.Move (System.String, System.String) в TestApp.MainWindow.MoveFile (System.String, System.String, System.String) в TestApp.MainWindow + d__11.MoveNext () в системе.Runtime.CompilerServices.AsyncMethodBuilderCore + <> c.b__6_1 (System.Object) в System.Threading.QueueUserWorkItemCallback.WaitCallback_Context (System.Object) в System.Threading.ExecutionContext.ThingContextContextTextInInSystem.Object, Boolean) в System.Threading.ExecutionContext.Run (System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean) в System.Threading.QueueUserWorkItemCallback.System.Threading.ITorkIteSystem.Threading.ThreadPoolWorkQueue.Dispatch () в System.Threading._ThreadPoolWaitCallback.PerformWaitCallback ()

Я использую FileSystemWatcher, который настроен так:

fileSystemWatcher = new FileSystemWatcher();
fileSystemWatcher.Path = path;
fileSystemWatcher.EnableRaisingEvents = true;
fileSystemWatcher.Created += FileCreated;

Когда файл добавляется в отслеживаемую папку, я выполняю эту функцию:

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

Очередь, в которую добавляется путь, определяется следующим образом, поскольку я хочу реагировать, как только файл добавляется:

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();
            OnCollectionChanged(NotifyCollectionChangedAction.Remove, item);

            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 propertyName)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }

Всякий раз, когда путь добавляется вочередь, в которой я выполняю эту функцию:

private async void ProcessFile(object sender, NotifyCollectionChangedEventArgs e)
        {
            while (paths.Count > 0)
            {
                var currentPath = paths.Dequeue();
                await upload(currentPath);
                Thread.Sleep(5000);
                MoveFile(currentPath, outputFolder, System.IO.Path.GetFileName(currentPath));
            }
        }

Мой MoveFile довольно прост:

private void MoveFile(string from, string to, string filename)
        {
            File.Move(from, to + "\\" + filename);
        }

Я попытался добавить Thread.Sleep(), чтобы убедиться, что файловая система выполнена с файломпрежде чем переместить его.Есть идеи, почему и как я могу исправить ошибку?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...