Правильно ли я использовал RowFilter в DataView с многопоточностью? - PullRequest
2 голосов
/ 04 марта 2012

РЕДАКТИРОВАТЬ: я использую VS2008, .NET 3.5

У меня есть DataTable, который заполняется в DataView и передается в CollectionView.

   DataTable newLeadTable = new DataTable();
   myConnection.Open();
   dbAdpater.Fill(newLeadTable);
   this.LeadDataView = new DataView(newLeadTable);
   this.LeadsCollectionView = 
   CollectionViewSource.GetDefaultView(this.LeadDataView);

Тогда DataGrid, который используется для отображения данных, привязывается к this.LeadsCollectionView

После того, как пользователь введет текст фильтра в View, ViewModel выполнит этот метод для установки строки фильтра в DataView:

private void SetLeadListFilter(string LeadFilterStr)
{
  this.LeadDataView.RowFilter = filterString;
}

Работает нормально, я вижу, что DataGrid показывает правильно отфильтрованный DataRow.

Но тогда я хочу дать некоторый интерфейс, добавить индикатор занятости. Поэтому я поместил приведенный выше код в поток:

this.IsBusy = true;
Thread filterDataThread= new Thread(new ThreadStart(() =>
{        
    this.LeadDataView.RowFilter = filterString;
    this.IsBusy = false;
}));
filterDataThread.Start();

Теперь странно, я вижу, что код был запущен, фильтр был установлен. Но DataGrid не фильтрует строки!

Итак, теперь я изменяю метод, переназначаю DataView в CollectionView снова:

this.IsBusy = true;
Thread filterDataThread= new Thread(new ThreadStart(() =>
{        
    this.LeadDataView.RowFilter = filterString;
    this.LeadsCollectionView = CollectionViewSource.GetDefaultView(this.LeadDataView); //Added this
    this.IsBusy = false;
}));
filterDataThread.Start();

Теперь это работает! Данные корректно фильтруются в DataGrid!

Так почему же это происходит, когда я использую многопоточность? Это правильный способ использовать DataFilter в Threading?

1 Ответ

0 голосов
/ 06 апреля 2012

Не могу сказать наверняка, но, как я понимаю, вы используете

CollectionViewSource.GetDefaultView(this.LeadDataView);

, чтобы получить источник данных для вашей DataGrid.Ответ основан на этом предположении.
Так что если вы будете вызывать этот метод за пределами filterDataThread, например так:

this.IsBusy = true;
Thread filterDataThread= new Thread(new ThreadStart(() =>
{        
    this.LeadDataView.RowFilter = filterString;
    this.IsBusy = false;
}));
filterDataThread.Start();
this.LeadsCollectionView =  
  CollectionViewSource.GetDefaultView(this.LeadDataView);

, тогда код с GetDefaultView, вероятно, будет выполняться до1011 * Ваша работа с потоками - будет гонка между MainThread и filterDataThread и MainThread победами, и ваш DataGrid не будет фильтровать данные.

Но если вы будете использоватькод, который вы указали:

this.IsBusy = true;
Thread filterDataThread = new Thread(new ThreadStart(() =>
{        
    this.LeadDataView.RowFilter = filterString;
    this.LeadsCollectionView =  
      CollectionViewSource.GetDefaultView(this.LeadDataView); //Added this
    this.IsBusy = false;
}));
filterDataThread.Start();

фильтрация начнется в нужное время.
Итак, ответ:
Да, вы делаете фильтрацию правильно.Но вы должны добавить код для обработки ошибок при выполнении операций в фоновом потоке, чтобы ваше приложение не было Busy навсегда.

Кроме того, вы должны проверить безопасный доступ к filterString - если вызапустите два или более потоков для фильтрации, будет другая гонка с непредсказуемыми результатами.

...