Установка Form.Owner для формы из другого потока

Мое приложение (C#, VS2008) загружает информацию из базы данных (SQL Server 2008 Express) по сети. Во время (возможно) долгого ожидания я хочу, чтобы диалоговое окно "Загрузка..." работало в другом потоке, но только если операция занимает больше определенного периода времени (скажем, 500 мс).

Итак, до сих пор моя форма загрузки отображалась через 500 мс (если операция длится так долго), не устанавливая владельца формы диалога загрузки (т.е. вызывая LoadingDialog.ShowDialog()), но когда я пытаюсь вызвать LoadingDialog.ShowDialog(IWin32Window владелец) с владельцем, установленным в основную форму (передается через параметр потока), я получаю InvalidOperationException о доступе к элементам управления через потоки.

Мой основной вопрос: могу ли я создать и ShowDialog форму с параметром владельца, установленным на форму в другом потоке? Я хочу сделать это так, чтобы диалог загрузки был модальным для остальной части приложения, то есть, как и любой другой диалог, фокусировался и запрещал ввод в другом месте.

Кто-нибудь может предложить предложение? Я прочитал кучу об заставках без удачи, а также об Invoke и BeginInvoke без удачи. Есть ли другой способ, которым я должен пойти по этому поводу?

Пожалуйста, не стесняйтесь просить разъяснений, если вы не понимаете.

Мерси (как говорят по-французски),

Иаков.

3 ответа

Решение

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

Другой вариант - показать ход загрузки в строке состояния или аналогичной. Ключ должен гарантировать, что длинная операция сделана в фоновом потоке, и вся логика GUI сделана в потоке GUI.

Хороший формат потоков может выглядеть следующим образом (это просто псевдокод для демонстрационных целей - вам нужно использовать Invoke, чтобы получить соответствующие потоки):

RunInBackground(DoLongOperation);
ShowLoadingDialog();
...

DoLongOperation()
{
    LongOperation();
    RunOnGUI(FinishLongOperation);
}

FinishLongOperation()
{
   CloseLoadingDialog();
}

Все компоненты пользовательского интерфейса работают в единственном единственном потоке, который проходит через цикл сообщений win32. Вы не можете запустить любой компонент пользовательского интерфейса в другом потоке. Эта архитектура сохраняется с Windows 3.1.

Вы МОЖЕТЕ создать столько потоков пользовательского интерфейса, сколько захотите. Следующий код должен сделать трюк:

    Thread thread = new Thread(new ThreadStart(() => Application.Run(new MyForm())));
    thread.SetApartmentState(ApartmentState.STA);
    thread.IsBackground = true;
    thread.Start();
Другие вопросы по тегам