WaitDialog, когда графический интерфейс требует времени

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

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

Мой вспомогательный класс выглядит так:

public class ProgressWaitDialogHelper : IDisposable
{
    private Thread _thread = null;

    public void ShowDialog()
    {
        ThreadStart threadStart = new ThreadStart(ShowDialogAsync);
        _thread = new Thread(threadStart);
        _thread.SetApartmentState(ApartmentState.STA);
        _thread.Start();
    }

    public void Dispose()
    {
        if ((_thread != null) &&
            (_thread.IsAlive))
        {
            _thread.Abort();
        }
    }

    private void ShowDialogAsync()
    {
        ProgressWaitDialog waitDialog = new ProgressWaitDialog();
        waitDialog.ShowDialog();
    }
}

Код для вызова вспомогательного класса в моем главном окне графического интерфейса выглядит следующим образом:

using (ProgressWaitDialogHelper waitDialog = new ProgressWaitDialogHelper())
{
    waitDialog.ShowDialog();

    // Do long running GUI task on main thread here.
}

Кажется, это работает нормально и выглядит именно так, как я хочу в графическом интерфейсе. Форма WaitDialog является модальной и блокирует доступ к основной форме графического интерфейса до тех пор, пока она не закончит свои обновления. Как только длительная задача графического интерфейса будет завершена, она выпадет из блока Using и, таким образом, вызовет метод Dispose в вспомогательном классе, который, в свою очередь, вызовет Abort в потоке.

Мой вопрос: есть ли более изящный способ завершить поток или лучший способ добиться того же поведения?


person millie    schedule 10.05.2011    source источник


Ответы (1)


Я бы предложил выполнить реальную работу в рабочем потоке и показать диалоговое окно ожидания в потоке графического интерфейса. Затем вы можете сигнализировать своему основному потоку, когда работа выполнена, и по завершении работы поток может изящно завершиться обычным образом, и вы можете просто убить свой диалог ожидания, как если бы вы убили любой другой диалог.

person Tony The Lion    schedule 10.05.2011
comment
Это не сработает, потому что длительная задача связана с компонентами графического интерфейса, созданными в основном потоке. Вы не можете обновлять компоненты графического интерфейса в рабочем потоке. Поскольку основной поток занят обновлением графического интерфейса, он не может создать модальное диалоговое окно ожидания, потому что тогда элемент управления графического интерфейса не сможет обновляться. Насколько я понимаю, диалоговое окно ожидания должно быть создано в рабочем потоке. - person millie; 12.05.2011
comment
@user, вы не сказали этого в своем вопросе, откуда я должен это знать, но если это так, я хотел бы знать, КАКАЯ это работа над компонентами графического интерфейса? - person Tony The Lion; 12.05.2011
comment
Вы должны это знать, потому что я упомянул, что в первых двух строках, которые я написал в своем вступительном посте, у меня есть приложение, которому может потребоваться много времени для выполнения некоторых обновлений графического интерфейса. Я не могу запустить это в фоновом потоке, потому что долгая обработка связана с обновлением компонентов графического интерфейса, которое можно выполнить только в основном потоке. Я действительно не понимаю, как я могу быть яснее, чем это. Что касается подробных сведений о фактической работе компонентов графического интерфейса, я хотел бы более подробно остановиться на этом, но я не думаю, что это действительно имеет значение или помогает в предоставлении решения. - person millie; 02.06.2011