ObservableCollection в Backgroundworker

262
09 декабря 2016, 08:53

Есть метод поиска файлов:

static public void FindLibrarys(String directoriesPath)
{
    ...
    //Ищет файлы. Каждый найденный файл передаёт в метод.
    ProgramsList.FormationProgramsList(file); 
}

Этот метод обрабатывает файл и помещает в свою ObservableCollection:

static public void FormationProgramsList(String file)
{
    ...
    // NewData возвращает новый экземпляр структуры.
    _fileList.Add( NewData(
                          fileName +
                          " | x" + bitCapacityProgram +
                          " | " +
                          myFileInfo.DirectoryName +
                          fileVersion +
                          productName,
                          _fileList.Count,
                          bitCapacityProgram == KompasCapacity
                        )
               );
}

Во ViewModel происходит привязка этой коллекции с коллекцией модели:

public ProjectViewModel()
{
    InitializeComponent();
    _model = (ProjectModel)this.Resources["Model"];
    backgroundWorker = ((BackgroundWorker)this.FindResource("backgroundWorker"));
     _model.ProgramsList = ProgramsList.FileList;
    // Ну и с самим контроллом
    ResultName.ItemsSource = _model.ProgramsList;
}

Так вот мне надо было сделать этот поиск по кнопке, но чтобы интерфейс не подвисал. Я сделал через Application.DoEvent, но это Windows.Forms. По этому мне сказали попробовать другими средствами. Я решил попробовать через BackgroundWorker.

В VM, в обработчике кнопки вызываю:

backgroundWorker.RunWorkerAsync();

И написал такой код:

private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
    foreach (String path in _model.SearchPathsList)
    {
        if (_isContinueSearch)
        {
            LibraryFinder.FindLibrarys(path);
        }
        else
            break;
    }
}

Всё запускается, только при первом же найденном файле выдаёт исключение: System.NotSupportedException при добавлении элемента в коллекцию _fileList в методе FormationProgramsList.

Вопросы:

  1. Можно ли с моей архитектурой проекта сделать, чтобы работало?
  2. Не стоит ли изменить архитектуру?
  3. Есть ли более удобные средства, которые можно было бы использовать вместо BackgroundWorker?

Изменения:

// Здесь я просто возвращаю кнопку в исходное состояние, т.к. при первом нажатии она меняет параметры и становится кнопкой остановки поиска.
private void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    // Возврат параметров поиска в исходное состояние.
    FindApp.Tag = true;
    FindApp.Content = "Найти приложения";
}

А ProgressChanged нету.

Answer 1

В таком случае нужно добавить обработчик события ProgressChanged и установить свойство WorkerReportsProgress="True" (там же в xaml, где добавляли обработчик 'DoWork`).

private void backgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
     string file = (string)e.UserState;
     ProgramsList.FormationProgramsList(file); 
}
private void FindLibrarys(String directoriesPath)
{   
    //Ищет файлы. Каждый найденный файл передаёт в метод.
    backgroundWorker.ReportProgress(0, file);
}

К тому же сделать методы не статическими, иначе не будет доступа к backgroundWorker или передать ссылку на backgroundWorker в метод FindLibrarys.

READ ALSO
Замена по регулярке

Замена по регулярке

Допустим, имеется текст text1(text2)text2 нужно получить text1 (text2) text2

287
Как определить текущий DispatcherPriority из метода который выполняет Dispatcher?

Как определить текущий DispatcherPriority из метода который выполняет Dispatcher?

Как определить текущий DispatcherPriority из метода который выполняет Dispatcher? Если я запускаю какой–то метод через Dispatcher с приоритетом (для примера)...

308
DataTableAdapter Report Viewer C# WinForms

DataTableAdapter Report Viewer C# WinForms

После компиляции приложения, не работает отчет в reportViewer если рядом с файломexe не лежит XML файл, в котором при компиляции прописывается сервер,...

293