FileSystemWatcher — создание нового файла, когда FileSystemWatcher наблюдает, а затем попытка доступа к нему дает мне ошибку

avatar
Hasarr
9 августа 2021 в 03:08
90
0
1

Я новичок в C# WPF и пытаюсь создать приложение, которое использует DataTable и записывает эту DataTable в файл XML с помощью метода DataTable.WriteXML(). Затем файл XML считывается DataGrid из ListView (selectedList).

 private void refreshDataGrid(DataGrid dataGridName, ListView selectedList, string path)
    {
        FileStream file;
        //check if the item from ListView is selected
        if (selectedList.SelectedItem != null)
        {
            try
            {
                file = File.Open(path + "\\" + selectedList.SelectedItem.ToString() + ".xml", FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
            }
            catch (Exception x)
            {
                MessageBox.Show(x.Message.ToString());
                return;
            }
            //clear the defaultData DataSet so it doesn't have any content
            defaultData.Tables.Clear();
            //read XML file
            defaultData.ReadXml(file);
            file.Close();
            dataGridName.ItemsSource = defaultData.Tables[0].DefaultView;
        }

DataGrid доступен для редактирования пользователем, и когда он выполняет редактирование содержимого, оно сохраняется в файле XML, а затем FileWatcher отслеживает изменения в последнем доступе к файлу, поэтому, когда содержимое файла изменяется, datagrid будет обновлен.

FileSystemWatcher fileWatcher = new();
private void CreateFileWatcher(string path)
    {
        fileWatcher.Path = path;
        fileWatcher.NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.LastAccess | NotifyFilters.Size | NotifyFilters.FileName;
        fileWatcher.Filter = "*.xml";
        fileWatcher.Changed += FileWatcher_Changed;
        fileWatcher.EnableRaisingEvents = true;
    }

    
    // Event for filewatcher throws an Exception
    
    private void FileWatcher_Changed(object sender, FileSystemEventArgs e)
    {
        Application.Current.Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Normal, (Action)(() =>
         {
             try
             {
                 refreshDataGrid(dataGridName, userListView, path);
             }
             catch(Exception)
             {
                 return;
             }
         }));
    }

Итак, проблема в том, что когда я создаю НОВЫЙ XML-ФАЙЛ во время работы приложения, а затем пользователь открывает этот файл в DataGrid и редактирует поле в DataGrid, данные сохраняются в XML-файл, как и должно быть. , и FileWatcher вызывается, поэтому, когда FileWatcher пытается обновить Datagrid, я получаю это сообщение:

Не удалось найти UIElementAutomationPeer.cs Вам нужно найти UIElementAutomationPeer.cs для просмотра источника текущего вызова. кадр стека System.ArgumentNullException: «Значение не может быть нулевым. Arg_ParamName_Name».
Необработанное исключение типа «System.ArgumentNullException» в PresentationCore.dll Значение не может быть нулевым.

Когда я создаю файл XML и перезапускаю приложение, все работает нормально. Также, когда файл был создан до запуска приложения, FileWatcher работает нормально. Я предполагаю, что вновь созданные файлы (во время выполнения приложения) не обновляются самим приложением, и ему необходимо обновить пользовательский интерфейс, но я не знаю, как это сделать. Мой FileWatcher также является глобальным, поэтому, возможно, это может быть проблемой, или мне следует как-то обновить FileWatcher? Будем признательны за любую помощь.

РЕДАКТИРОВАТЬ: я думаю, что есть проблема при создании файла в моей программе, возможно, приложение хочет использовать один и тот же файл дважды или не может получить к нему доступ, вот код:

private void saveTableToXML()
    {

        DataTable dt = new DataTable();
    dt = ((DataView)dataGridName.ItemsSource).ToTable();
        try
        {
            FileStream file = File.Create(path + "\\.xml");  
            dt.WriteXml(file, XmlWriteMode.WriteSchema,false);
            file.Close();
        }
        catch(Exception ex)
        {
            MessageBox.Show(ex.Message.ToString());
        }
       
    }
Источник
Zer0
9 августа 2021 в 03:11
1

Можете ли вы опубликовать сообщение об исключении и стек вызовов. Эта ошибка кажется чем-то, что IDE покажет, если в нее не загружены PDB. Не фактическое исключение.

Hasarr
9 августа 2021 в 03:26
0

Стек вызовов: PresentationCore.dll!System.Windows.Automation.Peers.UIElementAutomationPeer.FromElement (элемент System.Windows.UIElement) Строка 70 C#

Hasarr
9 августа 2021 в 03:27
0

Сообщение об исключении: {"Значение не может быть нулевым. (Параметр "элемент")"} System.ArgumentNullException

Zer0
9 августа 2021 в 03:28
0

Какая строка кода выше вызывает это исключение? Вы можете отредактировать свой вопрос, поместив его в код, например //this line throws the exception. Лучше, чем комментировать, чтобы все могли видеть это в вопросе. Я бы также предложил установить точку останова в refreshDataGrid и выполнить метод построчно, чтобы вы могли убедиться, что он делает то, что вы думаете.

Hasarr
9 августа 2021 в 03:36
0

Я отлаживал refeshDataGrid, но он отлично работает до последней строки кода, теперь я отредактировал вопрос.

Zer0
9 августа 2021 в 03:39
0

Итак, эта строка dataGridName.ItemsSource = defaultData.Tables[0].DefaultView; выдает исключение? Это было бы моим предположением. Проверьте эти значения, возможно, это не то, что вам нужно. Может быть, нет таблицы или представления по умолчанию?

Hasarr
9 августа 2021 в 03:42
0

Нет, исключение каким-то образом вызывается функцией FileSystemWatcher, ItemsSource успешно изменяется

Zer0
9 августа 2021 в 03:43
0

Хорошо, какая линия бросает? Если у вас подключен отладчик, он выделит строку кода. Это блок try catch, который у вас есть в событии? Я бы избавился от этого или сделал что-то полезное с исключением.

Hasarr
9 августа 2021 в 03:50
0

FileWatcher_Changed() выдает исключение, чтобы было ясно: если я удаляю refreshDataGrid() из FileWatcher_Changed(), он работает нормально, потому что после удаления он ничего не делает.

Zer0
9 августа 2021 в 03:52
0

Это означает, что какая-то строка в refreshDataGrid выбрасывается. Нам нужна эта линия. Или это то, как вы его вызываете. Вы можете просто сделать this.BeginInvoke. Вы также можете проверить InvokeRequired, чтобы узнать, находитесь ли вы уже в потоке GUI.

Hasarr
9 августа 2021 в 04:00
0

Я добавил окно сообщений после refreshDataGrid() в FileWatcher_Changed(), и отображается MessageBox, так что это означает, что refreshDataGrid() не бросает, я думаю

Bent Tranberg
9 августа 2021 в 04:16
1

Моя первоначальная мысль заключалась в том, что файл читается, пока он еще записывается. Наблюдатель за файлами прослушивает целую кучу вещей. Если я правильно понимаю, это одно и то же приложение пишет и читает файл, поэтому я вообще не понимаю необходимости в наблюдателе за файлами. Почему бы просто не подать внутренний сигнал о том, что происходит? Кроме того, записывайте в средство просмотра (консоль?), что происходит, вместо использования отладчика.

Flydog57
9 августа 2021 в 05:24
1

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

Caius Jard
9 августа 2021 в 05:52
0

Правильно ли я понимаю, что ваша программа создает строку в таблице данных, записывает таблицу данных на диск, использует fsw для обнаружения записываемого файла, загружает его с диска и отображает в таблице данных? Знаете ли вы, что вы можете полностью исключить диск и fsw из него и заставить строку отображаться в сетке с помощью всего одной строки кода? Передача данных между различными частями вашей программы путем их записи на диск и обратного чтения смехотворна..

Hasarr
10 августа 2021 в 21:55
0

Я добавил свой код для создания нового XML-файла в своем приложении. Возможно ли, что я неправильно закрыл файл?

Ответы (0)