Winforms C # - Показать диалог отмены, когда основной поток пользовательского интерфейса занят - PullRequest
2 голосов
/ 22 ноября 2011

У меня есть основная форма, которая содержит элемент управления для редактирования, который занимает всю форму. Существует другой рабочий поток, который постоянно записывает сообщения журнала в этот элемент управления редактирования. Теперь я хочу показать диалоговое окно с кнопкой «Отмена», когда основной элемент управления редактирования пользовательского интерфейса отображает данные. Проблема в том, что диалог отмены не отвечает, пока за ним происходят обновления, и я не могу нажать на кнопку отмены. Любая идея о том, как ее решить. Я думал о создании другого потока пользовательского интерфейса и показать кнопку отмены из него. Любые другие альтернативы?

EDIT # 1

  1. Я должен уточнить, что я уже использую рабочий поток для выполнения работы.
  2. DisplayLogs () находится в отдельном потоке.
  3. DisplayLogs () вызывается из других потоков.
  4. LogMessage - делегат, указывающий на метод UpdateMessage в основном пользовательском интерфейсе.
  5. Используется элемент управления TextBox. Я пробовал другие элементы управления, такие как просмотр списка, richtextboxsand и т. д. все тот же результат.

Рабочая нить

void DisplayLogs()
{
    lock (this)
    {
        while (logQueue.Count > 0)
        {
            string logMessagemessage = logQueue.Dequeue();
            LogMessage(string.Concat(logMessagemessage, Environment.NewLine));
        }
    }
}

Основной интерфейс

public void UpdateMessage( string message)
{
    if (!txtLog.IsHandleCreated)
    {
        return;
    }

    if (txtLog.InvokeRequired)
        txtLog.BeginInvoke( new UpdateLogDelegate( UpdateLog), message);
    else
        txtLog.AppendText(message);
}

Ответы [ 4 ]

3 голосов
/ 22 ноября 2011

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

MSDN - Как использовать Background Worker

0 голосов
/ 05 июня 2013

Ваша проблема в том, что ваш поток пользовательского интерфейса ВСЕГДА занят.Я говорю это, предполагая, что количество элементов в logQueue довольно велико.Цикл while не завершается, пока очередь не опустеет.Так что он продолжает попадать в поток пользовательского интерфейса с запросом обновлений.

Также if (txtLog.InvokeRequired) отчасти бессмысленно, потому что вы всегда вызываете метод из рабочего потока.

Итак, так как a.Приложение net WinForm имеет только один пользовательский интерфейс, который в вашем случае слишком занят для обработки других уведомлений, новое окно выглядит застрявшим (поскольку сообщения рисования застряли в очереди сообщений и не могут быть обработаны, так как они уже заполнены текстовым полемобновить сообщения)

Вы можете вставить Application.DoEvents в ваш цикл, что даст циклу сообщений некоторое время для обработки ожидающих уведомлений.Однако, на мой взгляд, это своего рода хак, поскольку поведение пользовательского интерфейса иногда непредсказуемо.Это может привести к таким вещам, как заикание при перемещении диалога, задержка ответов на события щелчка и т. Д.

Другой пункт, MessageBox.Show или Form.ShowDialog (если вы используете это для кнопки отмены),блокирующий вызов.Нить, на которой вы показываете это, будет висеть, пока вы не закроете диалог.Попробуйте Form.Show и установите для родительского свойства основную форму.

Другой альтернативой является добавление таймера и обработка только X уведомлений в течение Y секунд.Это даст потоку пользовательского интерфейса некоторое пространство для выполнения других действий.

0 голосов
/ 22 ноября 2011

В этой ситуации необходимо переместить большую часть работы в новый поток и очистить поток пользовательского интерфейса для сообщений об отмене и т. Д.

0 голосов
/ 22 ноября 2011

Вы идете об этом задом наперед. Основной поток, по идее, всегда должен быть доступен для принятия пользовательского ввода. Все, что может блокироваться в течение длительных периодов времени (тяжелые вычисления, доступ к базе данных, доступ к сети), должно выполняться в фоновом потоке. Идея состоит в том, чтобы данные элемента управления для редактирования вычислялись и заполнялись фоновым потоком (BackgroundWorker объекты здесь хорошо работают), чтобы основной поток всегда был доступен, если пользователь нажимает кнопку отмены.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...