我目前正在开发一个Windows.Forms应用程序。这基本上是一个简单的运动检测问题。
我在窗体上有一个按钮,当按下按钮时,启动一个后台工作人员,它执行以下操作:
(sender as BackgroundWorker).ReportProgress((Bitmap)buffer.Clone())在“进度更改”事件中,我将缓冲区绘制到屏幕上。
if (!PnlImage.IsDisposed)
PnlImage.CreateGraphics().DrawImageUnscaled(buffer, 0, 0);我不禁想知道,这是否是在屏幕上绘制更新图像的最佳方式。有人能建议我做些什么改进吗?谢谢。
编辑:我已经更新了程序以使用.NET框架4,我们不再使用BackgroundWorker。相反,我们现在使用System.Threading.Tasks名称空间,并使用Invoke从任务中更新背景图像。
感谢所有的回复。
发布于 2010-01-10 02:10:03
我认为,您可能遇到的任何问题的根源在于,任何GUI更新都必须在UI线程上进行。您无法从另一个线程安全地更新UI。因此,基本上,您需要这样做(我只是改变背景颜色作为一个例子,但您可以做您喜欢的任何事情):
private void SomethingCalledFromBackgroundThread()
{
panel1.Invoke(new DoUpdatePanel(UpdatePanel), Color.Blue);
}
private delegate void DoUpdatePanel(Color aColor);
private void UpdatePanel(Color aColor)
{
panel1.BackColor = aColor;
}============更新=======>
你曲解了我的答案。我没有说要从ProgressChanged内部调用Invoke。@Jean请记住ReportProgress/ProgressChanged是异步运行的--这就是为什么您发现自己正在复制自己的图像。如果您在后台线程中使用Invoke,而不是使用ReportProgress,则这是不必要的。
发布于 2010-01-10 00:54:53
我不确定这是否是严格正确的,但我确信您不能在单独的线程上跨线程GUI/Control操作,因为默认情况下,它是在专用GUI线程上处理的。
我之前尝试过做类似的事情,最后我决定用一种完全不同的方法来处理它,因为将属性设置为false是让它工作的最差方法。
发布于 2010-01-10 05:57:13
ProgressChanged和RunWorkerCompleted事件允许您直接更新UI。只有DoWork事件处理程序才不能访问from。见MSDN
您必须小心不要操作DoWork事件处理程序中的任何用户界面对象。相反,通过ProgressChanged和RunWorkerCompleted事件与用户界面通信。
这是使用BackgroundWorker而不是创建自己的线程的主要好处之一。因此,TheObjectGuy是不正确的,您不需要在ProgressChanged中使用BeginInvoke/Invoke。
只要您的图像不太大,克隆它就不会引起任何严重的性能问题。如果你有问题的话,用更大的图片运行一些性能测试。
否则,为了避免棘手的同步问题,如使用锁,我认为复制图像是保持简单的好方法。
https://stackoverflow.com/questions/2035087
复制相似问题