События из другого потока в C # - PullRequest
1 голос
/ 06 марта 2011

У меня есть такой код: 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 ГБ) progressBar по какой-то причине останавливается на некотором значении на этапе разделения.Но расщепление было закончено.В чем причина этих странностей?PS Я пишу это на Mono и Gtk #.

Ответы [ 2 ]

3 голосов
/ 06 марта 2011

Как и в winforms, Gtk имеет сходство с потоками.Ваши обновления должны происходить в основном цикле пользовательского интерфейса.Это можно сделать с помощью:

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

См. Также примечания mono Best Practices .

2 голосов
/ 06 марта 2011

Вы не можете трогать объекты GUI из потока, не являющегося GUI. Результаты непредсказуемы. Иногда это вызывает исключение, но не всегда.

Вместо этого используйте метод Invoke или BeginInvoke (первый лучше). Вот так:

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