Как заставить Sleep on background работать с Invoke - PullRequest
1 голос
/ 27 октября 2009

У меня есть элемент управления PictureBox на форме, который должен рисовать что-то каждые 100 мс.

Фоновый поток выполняет некоторые вычисления в цикле и после каждой итерации запускает событие.

Отредактировано (в ответ на комментарий) :

World world = new World();

void CreateBackgroundThread() {
    Thread backgroundThread = new Thread(world.BackgroundWorkerFunction);
    backgroundThread.Start();
}

public class World { 

    void BackgroundWorkerFunction() {
        IPiece piece = PieceFactory.Create();
        for (int i = 0; i < stepsCount; i++) {
            piece.Calculate();
            if (OnPieceStep != null) {
                OnPieceStep(piece);
            }
        }
    }

}

Внутри основной формы есть обработчик, установленный:

world.OnPieceStep += DrawScreen;

и обертка Invoke (поскольку элемент управления, к которому следует обращаться, создается в потоке пользовательского интерфейса).

void DrawScreen(IPiece piece) {
    this.Invoke(new PieceStep(_drawScreen), piece);
}
void _drawScreen(IPiece piece) {
    drawer.Draw(world.Board, piece);
}

Теперь я бы хотел, чтобы for loop приостанавливал 100 мс после каждой итерации, поэтому я добавил Thread.Sleep (100); перед запуском события:

for (int i = 0; i < stepsCount; i++) {
    IPiece piece = Calculate();
    if (OnPieceStep != null) {
        Thread.Sleep(100);
        OnPieceStep(piece);
    }
}

Это, однако, не обновляет pictureBox каждые 100 мс, но рисует только последнюю итерацию цикла и только после его завершения.

Не должен ли Thread.Sleep приостановить поток, в котором он вызывается, а не поток пользовательского интерфейса? Обновление: Я только что попытался нажать на приложение, пока вычисляется фоновая нить. Программа блокируется («не отвечает»), поэтому Thread.Sleep явно вызывался в потоке пользовательского интерфейса. Это ожидаемое поведение или что-то не так с моим потоком?

Ответы [ 2 ]

1 голос
/ 03 ноября 2009

Как указано на этой странице :

Тема. Сон является уникальным среди методы блокировки в том, что приостанавливает Перекачка сообщений Windows в пределах Приложение Windows Forms или COM среда в потоке, для которого однопоточная модель квартиры используемый. Это мало что значит с приложениями Windows Forms, в что любая длительная операция блокировки на основной поток пользовательского интерфейса сделает приложение не отвечает - и есть следовательно, вообще избегают - независимо или нет сообщение прокачка "технически" приостановлено. ситуация сложнее в наследство Среда размещения COM, где это возможно иногда хочется спать пока поддерживая прокачку сообщений. Крис Брамм из Microsoft обсуждает это подробно в его веб-журнале (поиск: 'COM "Chris Brumme"').

Кажется, что Thread.Sleep () в WinForms всегда приостанавливает интерфейс, независимо от того, в каком потоке вызывается.

1 голос
/ 27 октября 2009

С точки зрения перспективы все выглядит хорошо. Скорее всего, проблема связана с методом _drawScreen (IPiece). Вы пытались обновить / обновить окно после рисования?

Некоторое понимание: Метод Control.Invoke передает делегат, предоставленный в качестве параметра, в виде сообщения окна, используя функцию Win32 SendMessage.

...