关于从后台线程更新的另一个问题。从后台线程更新UI
为了说明问题:在应用程序中,后台线程需要更新UI。我考虑过使用中间集合来缓冲消息,并有一个计时器来显示它们。目前我们正在尝试最简单的方法。
代码尝试#1:
void foo(string status)
{
if (this.InvokeRequired)
{
BeginInvoke(new MethodInvoker(delegate()
{
InsertStatusMessage(status);
}));
}
else
{
InsertStatusMessage(status);
}
}
这似乎有一些瑕疵。 Msdn指出,如果尚未创建窗口句柄(在我看来,不可用),InvokeRequired
也返回false
。所以代码应该是:
void foo(string status)
{
if (this.InvokeRequired)
{
BeginInvoke(new MethodInvoker(delegate()
{
InsertStatusMessage(status);
}));
// wait until status is set
EndInvoke(result);
}
else if(this.IsHandleCreated)
{
InsertStatusMessage(status);
}
else
{
_logger.Error("Could not update status");
}
}
上面的代码也以某种方式抛出(对于未知和未复制的原因)。我们使用的DevExpress,这是未处理的异常消息(没有信息,也没有什么/错误发生的地点任何线索):
System.NullReferenceException:未设置为在 DevExpress的一个对象实例 对象引用。 Utils.Text.FontsCache.GetFontCacheByFont(图形图像, 字体的字体)的 DevExpress.Utils.Text.TextUtils.GetFontAscentHeight(图形克,字体 字体)在 DevExpress.XtraEditors.ViewInfo.BaseEditViewInfo.GetTextAscentHeight() 在 DevExpress.XtraEditors.ViewInfo.TextEditViewInfo.CalcTextBaseline(Graphics g)in DevExpress.XtraEditors.ViewInfo.BaseControlViewInfo.ReCalcViewInfo(图形 克,MouseButtons按钮,点mousePosition,矩形范围)在 DevExpress.XtraGrid.Views.Grid.ViewInfo.GridViewInfo.UpdateCellEditViewInfo(GridCellInfo 细胞,点mousePos结构,布尔canFastRecalculate,布尔计算值)在 DevExpress.XtraGrid.Views.Grid.ViewInfo.GridViewInfo.CreateCellEditViewInfo(GridCellInfo 细胞,布尔计算值,布尔allowCache)在 DevExpress.XtraGrid.Views.Grid.ViewInfo.GridViewInfo.RequestCellEditViewInfo(GridCellInfo 细胞)中 DevExpress.XtraGrid.Views.Grid.Drawing.GridPainter.DrawRegularRowCell在 的DevExpress(GridViewDrawArgs E,GridCellInfo CI)在 DevExpress.XtraGrid.Views.Grid.Drawing.GridPainter.DrawRow .XtraGrid.Views.Grid.Drawing.GridPainter.DrawRegularRow(GridViewDrawArgs E,GridDataRowInfo RI)(GridViewDrawArgs E,GridRowInfo RI)在 DevExpress.XtraGrid.Views .Grid.Drawing.GridPainter.DrawRows在 DevExpress.XtraGrid.Views.Grid.Drawing.GridPainter.Draw(ViewDrawArgs(GridViewDrawArgs e)在 DevExpress.XtraGrid.Views.Grid.Drawing.GridPainter.DrawContents(GridViewDrawArgs E) (在eX)中的DevExpress.XtraGrid.Views.Base.BaseView.Draw(GraphicsCache e)在System.Windows.Forms.Control.PaintWithErrorHandlin克(PaintEventArgs的 E,Int16的层,布尔disposeEventArgs)在 System.Windows.Forms.Control.WmPaint(消息&米) System.Windows.Forms.Control.WndProc(消息&米) DevExpress.XtraEditors。 DevExpress.XtraGrid.GridControl中的Container.EditorContainer.WndProc(消息& m)
。的WndProc(消息&米) System.Windows.Forms.Control.ControlNativeWindow.WndProc(消息&米)
在System.Windows.Forms.NativeWindow.Callback(IntPtr的的HWND,的Int32味精, IntPtr的WPARAM,IntPtr的LPARAM)
我想用Begin/End Invoke
,而不是Invoke
,因为它需要较少的东西(方法委托),它是更具可读性。
有什么我错过了,我怎么能放心地做线程调用?我只想在列表框中添加一条消息。我真的不在乎调用线程是否等待几毫秒。
为什么该方法在创建句柄之前触发?这看起来有点明显我 – 2012-04-12 09:37:37
@BoasEnkler我没有说它这样做。我不确定什么失败 – Odys 2012-04-12 09:38:21
有一些DevExpress控件根本无法使用Invoke从后台调用中更新。他们可能正忙着做一些将通过使用Invoke而被破坏的东西。使用另一种方法解决这个问题,并将数据结构更改/数据源设置为您的问题,以便我们有机会为您提供帮助。 – CodingBarfield 2012-04-12 09:44:30