Events from another thread in C#
I have a such code: http://pastie.org/1638879
I got it from someone's blog. It must sort big files. I preform it in separated thread:
protected virtual void goButton_Clicked (object sender, System.EventArgs e)
{
FileSort fileSort = new FileSort(fileNameEntry.Text, "./BigFileSorted.dat");
fileSort.SplitProgressChanged += fileSortProgressSplitting;
fileSort.SortChunksProgressChanged += fileSortProgressSorting;
fileSort.MergeProgressChanged += fileSortProgressMerging;
Thread thread = new Thread(fileSort.Sort);
thread.Start();
//fileSort.Sort();
}
protected virtual void fileSortProgressSplitting(FileSort o, double progress)
{
progressBar.Fraction = progress;
progressBar.Text = "Splitting...";
}
protected virtual void开发者_如何学编程 fileSortProgressSorting(FileSort o, double progress)
{
progressBar.Fraction = progress;
progressBar.Text = "Sorting...";
}
protected virtual void fileSortProgressMerging(FileSort o, double progress)
{
progressBar.Fraction = progress;
progressBar.Text = "Merging...";
}
For small files everything is normally, but for big files(about 4 gb), progressBar stops on some value for some reason during the splitting step. But splitting was finished. What is reason of this stranges? P.S. I'm writing it on Mono and Gtk#.
Like winforms, Gtk has thread affinity. Your updates should happen on the main UI loop. You can do this via:
protected virtual void fileSortProgressMerging(FileSort o, double progress) {
Gtk.Application.Invoke (delegate {
progressBar.Fraction = progress;
progressBar.Text = "Merging...";
});
}
See also the mono Best Practices notes on this.
You can't touch GUI objects from non-GUI thread. Results are unpredictable. Sometimes it will throw an exception, but not always.
Instead, use the Invoke
or BeginInvoke
method (former is better). Like so:
protected virtual void fileSortProgressSplitting(FileSort o, double progress)
{
BeginInvoke( new Action( () =>
{
progressBar.Fraction = progress;
progressBar.Text = "Splitting...";
} );
}
精彩评论