1

我正在编写一个在 PDA 上显示地图的 .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>
    }

你知道怎么做吗?还是我的方法完全错误?

谢谢你的时间!

4

5 回答 5

3

方法是错误的。更新 ui 的代码必须在 ui 线程上运行。如果你从另一个线程更新 ui,你会得到一个异常。

于 2008-09-23T12:04:23.113 回答
1

如果渲染地图很耗时并且您不想冻结 GUI 线程(使您的应用程序无响应),您可以将屏幕划分为单元格。使用后台线程将单元格渲染为位图,使用 Invoke 告诉 GUI 线程绘制完成的单元格,当调用返回时,让线程继续处理下一个单元格。

您需要直接在控件上绘制(而不是在 Paint() 内部),或者您需要调用一个 invalidateRect 并有一些逻辑来确保您计算的图像与系统希望您绘制的图像相匹配。

这将使您的图像逐渐出现,并且您的 UI 将具有响应性。如果用户进行了某种动作,不需要继续绘制,只需中止线程。

于 2008-09-26T23:48:08.567 回答
1

为了调用从另一个线程更新 UI 的函数,请使用 Form 的 Invoke 函数。

这是一个很好的参考

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

编辑:正如评论中指出的那样,如果您希望调用代码不等待 UI 线程,BeginInvoke 会更好。

于 2008-09-23T12:09:08.547 回答
1

在后台线程中的内存中绘制地图,然后在准备好时(在 UI 线程中)将该光栅图像渲染到屏幕上。如果可能,使用 BufferedGraphics,否则使用 GDI。

于 2008-09-23T14:19:07.237 回答
0

我建议你有某种从底层线程到主 UI 线程的消息传递系统。

这样,主 UI 线程进行所有更改并从底层线程触发。还要确保您可以使用这些消息发送一些数据,以防您想将一些复杂的信息发送回主 UI 线程。

于 2008-09-23T12:08:25.583 回答