Как обновить компоненты в разных темах? .NET CF - PullRequest
1 голос
/ 23 сентября 2008

Я программирую приложение .NET Compact Framework, которое показывает карты на КПК.

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

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

Правильно знать, что каждый фрагмент карты нарисован в своем методе onPaint. Моя идея состоит в том, чтобы как-то сказать системе: «Выполните этот код в потоке, пожалуйста».

Что-то вроде:

protected override void OnPaint(PaintEventArgs e)
    {
       // <code to be executed in a thread>
       e.Graphics.paintTHis();
       e.Graphics.paintThat();
       whateverItTakesToPaintThisPieceOfTheMap();
       // </code to be executed in a thread>
    }

Ты знаешь, как это сделать? Или мой подход просто неверен?

Спасибо за ваше время!

Ответы [ 5 ]

3 голосов
/ 23 сентября 2008

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

1 голос
/ 27 сентября 2008

Если рендеринг карты занимает много времени и вы не хотите останавливать поток графического интерфейса пользователя (приложение перестает отвечать на запросы), вы можете разделить экран на ячейки. Используйте фоновый поток, чтобы визуализировать ячейку как растровое изображение, используйте Invoke, чтобы сообщить GUI-потоку о необходимости отрисовать готовую ячейку, а когда invoke возвращается, пусть поток продолжит работу со следующей ячейкой.

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

Это заставит ваше изображение появляться постепенно, и ваш пользовательский интерфейс будет отзывчивым. Если пользователь выполняет какое-либо действие, которое не требует продолжения рисования, просто прервите поток.

1 голос
/ 23 сентября 2008

Нарисуйте карту в памяти в фоновом потоке, затем визуализируйте (в потоке пользовательского интерфейса) это растровое изображение на экране, когда будете готовы. Если возможно, используйте BufferedGraphics, в противном случае GDI.

1 голос
/ 23 сентября 2008

Чтобы вызвать функцию, которая обновляет пользовательский интерфейс из другого потока, используйте функцию Invoke формы.

Вот хороший справочник

http://weblogs.asp.net/justin_rogers/articles/126345.aspx

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

0 голосов
/ 23 сентября 2008

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

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

...