我正在编写一个.NET Compact Framework应用程序,它在PDA上显示地图。
我已经创建了一个ad hoc组件,它绘制了整个地图的一部分,使用这些组件中的几个组成了大图。我这样做是为了避免在一步中绘制整个地图的延迟。
我现在想要做的是在自己的线程中绘制这些部分,因此地图看起来会像单个实体一样增长(并且也更重要),以避免冻结用户界面的其余部分。
知道地图的每一块都是用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>
}
你知道怎么做吗?或者我的做法完全错了?
谢谢你的时间!
答案 0 :(得分:3)
方法错了。更新ui的代码必须在ui线程上运行。如果你从另一个线程更新ui,你会得到一个例外。
答案 1 :(得分:1)
为了调用从另一个线程更新UI的函数,请使用Form的Invoke函数。
这是一个很好的参考
http://weblogs.asp.net/justin_rogers/articles/126345.aspx
编辑:正如评论中所指出的,如果你希望调用代码不要等待UI线程,那么BeginInvoke会更好。
答案 2 :(得分:1)
在后台线程中在内存中绘制地图,然后在准备好时(在UI线程中)将光栅图像渲染到屏幕。如果可能,请使用BufferedGraphics,否则使用GDI。
答案 3 :(得分:1)
如果渲染地图非常耗时并且您不想冻结GUI线程(使应用程序无响应),则可以将屏幕划分为单元格。使用后台线程将单元格渲染为位图,使用Invoke告诉GUI线程绘制完成的单元格,当调用返回时,让线程继续使用下一个单元格。
您需要直接绘制到控件上(不在Paint()中)或者您需要调用invalidateRect并使用一些逻辑来确保计算出的图像与系统要绘制的图像相匹配。
这将使您的图片逐渐显示,并且您的用户界面将会响应。如果用户做出某种不需要继续绘制的动作,只需中止该线程即可。
答案 4 :(得分:0)
我建议你有一些从底层线程到主UI线程的消息传递系统。
这样,主UI线程进行所有更改并从底层线程触发。还要确保您可以使用这些消息发送一些数据,以防您想将一些复杂信息发送回主UI线程。