来自C#中另一个线程的事件

时间:2011-03-06 10:15:06

标签: c# mono gtk#

我有这样的代码:http://pastie.org/1638879

我是从某人的博客上得到的。它必须排序大文件。 我在分开的线程中预先形成它:

    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...";

}

对于小文件,一切正常,但对于大文件(大约4 gb),progressBar在分割步骤中由于某种原因停止某些值。但分裂完成了。这个奇怪的原因是什么? 附:我是在Mono和Gtk#上写的。

2 个答案:

答案 0 :(得分:3)

与winforms一样,Gtk具有线程亲和力。您的更新应在主UI循环上进行。您可以通过以下方式执行此操作:

protected virtual void fileSortProgressMerging(FileSort o, double progress) {
    Gtk.Application.Invoke (delegate {
        progressBar.Fraction = progress;
        progressBar.Text = "Merging...";
    });    
}

另请参阅mono Best Practices关于此的说明。

答案 1 :(得分:2)

您无法从非GUI线程触摸GUI对象。结果是不可预测的。有时它会引发异常,但并非总是如此。

相反,请使用InvokeBeginInvoke方法(以前更好)。像这样:

protected virtual void fileSortProgressSplitting(FileSort o, double progress)
{
    BeginInvoke( new Action( () =>
        {
            progressBar.Fraction = progress;
            progressBar.Text = "Splitting...";
        } );
}