ObservableCollection
文字列とintを保持するカスタムクラスがあります:
public class SearchFile
{
public string path { set; get; }
public int occurrences { set; get; }
}
コレクションを で表示したいdataGrid
。コレクションには、更新されるたびに通知するメソッドがあります。これまでのところ、DataGrid.ItemsSource
(正しい?) にリンクするだけです。グリッド XAML はdataGrid1.ItemsSource = files;
次のとおりです (C# コードビハインドを使用)。
<DataGrid AutoGenerateColumns="False" Height="260" Name="dataGrid1" VerticalAlignment="Stretch" IsReadOnly="True" ItemsSource="{Binding}" >
<DataGrid.Columns>
<DataGridTextColumn Header="path" Binding="{Binding path}" />
<DataGridTextColumn Header="#" Binding="{Binding occurrences}" />
</DataGrid.Columns>
</DataGrid>
現在、事態はより複雑になっています。path
最初に、デフォルト値のoccurrence
ゼロで sを表示したいと思います。SearchFile
次に、すべてを調べて、計算された値で更新したいと思いますoccurrence
。ヘルパー関数は次のとおりです。
public static void AddOccurrences(this ObservableCollection<SearchFile> collection, string path, int occurrences)
{
for(int i = 0; i < collection.Count; i++)
{
if(collection[i].path == path)
{
collection[i].occurrences = occurrences;
break;
}
}
}
プレースホルダー ワーカー関数は次のとおりです。
public static bool searchFile(string path, out int occurences)
{
Thread.Sleep(1000);
occurences = 1;
return true; //for other things; ignore here
}
BackgroundWorker
バックグラウンド スレッドとしてa を使用しています。方法は次のとおりです。
private void worker_DoWork(object sender, DoWorkEventArgs e)
{
List<string> allFiles = new List<string>();
//allFiles = some basic directory searching
this.Dispatcher.Invoke(new Action(delegate
{
searchProgressBar.Maximum = allFiles.Count;
files.Clear(); // remove the previous file list to build new one from scratch
}));
/* Create a new list of files with the default occurrences value. */
foreach(var file in allFiles)
{
SearchFile sf = new SearchFile() { path=file, occurrences=0 };
this.Dispatcher.Invoke(new Action(delegate
{
files.Add(sf);
}));
}
/* Add the occurrences. */
foreach(var file in allFiles)
{
++progress; // advance the progress bar
this.Dispatcher.Invoke(new Action(delegate
{
searchProgressBar.Value = progress;
}));
int occurences;
bool result = FileSearcher.searchFile(file, out occurences);
files.AddOccurrences(file, occurences);
}
}
実行すると、2つの問題があります。まず、進行状況バーの値を更新すると、The calling thread cannot access this object because a different thread owns it.
例外がスローされます。なんで?ディスパッチャにあるので、問題なく動作するはずです。そして 2 番目に、foreach
ループがbool result =...
行で中断されます。私はそれをコメントアウトして設定しようとしましたint occurences = 1
が、ループが回っていますが、何か奇妙なことが起こっています.ゼロ)。
なぜですか?