Я программирую приложение .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>
}
Вы знаете, как это сделать? Или мой подход просто неверен?
Спасибо за ваше время!





Подход неверный. Код, обновляющий пользовательский интерфейс, должен выполняться в потоке пользовательского интерфейса. Вы получите исключение, если обновите пользовательский интерфейс из другого потока.
Я бы предположил, что у вас есть какая-то система обмена сообщениями от базовых потоков к основному потоку пользовательского интерфейса.
Таким образом, основной поток пользовательского интерфейса вносит все изменения и запускается из базовых потоков. Также убедитесь, что вы можете отправлять некоторые данные с этими сообщениями, на случай, если вы хотите отправить сложную информацию обратно в основной поток пользовательского интерфейса.
Чтобы вызвать функцию, которая обновляет пользовательский интерфейс из другого потока, используйте функцию Invoke формы.
Вот хорошая ссылка
http://weblogs.asp.net/justin_rogers/articles/126345.aspx
Обновлено: как указано в комментариях, BeginInvoke было бы лучше, если вы хотите, чтобы вызывающий код не ждал потока пользовательского интерфейса.
Нет, Invoke выполняет вызов пользовательского интерфейса в потоке пользовательского интерфейса, но блокируется. BeginInvoke было бы лучше, хотя
Нарисуйте карту в памяти в фоновом потоке, а затем визуализируйте (в потоке пользовательского интерфейса) это растровое изображение на экране, когда оно будет готово. По возможности используйте BufferedGraphics, в противном случае - GDI.
Если рендеринг карты занимает много времени, и вы не хотите останавливать поток графического интерфейса (из-за чего приложение перестает отвечать на запросы), вы можете разделить экран на ячейки. Используйте фоновый поток для визуализации ячейки как растрового изображения, используйте Invoke, чтобы указать потоку графического интерфейса пользователя нарисовать законченную ячейку, когда вызов возвращается, пусть поток продолжит работу со следующей ячейкой.
Вам нужно будет рисовать непосредственно на элементе управления (не внутри Paint ()), или вам нужно будет вызвать invalidateRect и иметь некоторую логику, чтобы убедиться, что ваше вычисленное изображение соответствует тому, что система хочет, чтобы вы рисовали.
Это заставит ваше изображение появляться постепенно, а ваш пользовательский интерфейс будет отзывчивым. Если пользователь делает какое-то действие, которое делает ненужным продолжение рисования, просто прервите поток.
Invoke вызывает исходный поток, что противоречит цели.