我有一个C# WinForms应用程序。当启动主UI表单之前显示DevExpress XtraMessageBox时,将在静态void ()方法中抛出此异常。以下是代码(简化):
static void Main(string[] args)
{
// Display Splash Screen.
SplashForm.Start();
if (!CheckLicense())
XtraMessageBox.Show(null, "Not Licensed!", "License Check",
MessageBoxButtons.OK, MessageBoxIcon.Information);
using (MainForm form = new MainForm())
{
SplashForm.Stop();
if (form != null)
Application.Run(form);
}
}虽然它是一个DevExpress控件,但实际上在调用:
System.Drawing.Graphics.get_PageUnit()异常不会始终抛出。它可以在特定的机器上复制,但是一旦我在异常之前添加了一个MicroSoft MessageBox.Show()来显示调试信息,那么我就不再获得异常。下面是堆栈跟踪:
Object is currently in use elsewhere.
at System.Drawing.Graphics.get_PageUnit()
at DevExpress.Utils.Text.FontsCache.GetFontCacheByFont(Graphics graphics, Font font)
at DevExpress.Utils.Text.FontsCache.GetStringSize(Graphics graphics, String text, Font font, StringFormat stringFormat, Int32 maxWidth)
at DevExpress.Utils.Text.TextUtils.GetStringSize(Graphics g, String text, Font font, StringFormat stringFormat, Int32 maxWidth)
at DevExpress.Utils.Paint.XPaintMixed.CalcTextSize(Graphics g, String s, Font font, StringFormat strFormat, Int32 maxWidth)
at DevExpress.Utils.AppearanceObject.CalcTextSize(Graphics g, StringFormat sf, String s, Int32 width)
at DevExpress.Utils.AppearanceObject.CalcTextSize(Graphics g, String s, Int32 width)
at DevExpress.XtraEditors.Drawing.EditorButtonPainter.CalcCaptionSize(EditorButtonObjectInfoArgs e)
at DevExpress.XtraEditors.Drawing.EditorButtonPainter.CalcObjectMinBounds(ObjectInfoArgs e)
at DevExpress.XtraEditors.Drawing.SkinEditorButtonPainter.CalcObjectMinBounds(ObjectInfoArgs e)
at DevExpress.XtraEditors.ViewInfo.BaseButtonViewInfo.CalcBestFit(Graphics g)
at DevExpress.XtraEditors.BaseControl.CalcBestSize()
at DevExpress.XtraEditors.XtraMessageBoxForm.CreateButtons()
at DevExpress.XtraEditors.XtraMessageBoxForm.ShowMessageBoxDialog()
at DevExpress.XtraEditors.XtraMessageBoxForm.ShowMessageBoxDialog(XtraMessageBoxArgs message)
at DevExpress.XtraEditors.XtraMessageBox.Show(UserLookAndFeel lookAndFeel, IWin32Window owner, String text, String caption, DialogResult[] buttons, Icon icon, Int32 defaultButton, MessageBoxIcon messageBeepSound)
at DevExpress.XtraEditors.XtraMessageBox.Show(IWin32Window owner, String text, String caption, DialogResult[] buttons, Icon icon, Int32 defaultButton, MessageBoxIcon messageBeepSound)
at DevExpress.XtraEditors.XtraMessageBox.Show(IWin32Window owner, String text, String caption, MessageBoxButtons buttons, MessageBoxIcon icon, MessageBoxDefaultButton defaultButton)
at DevExpress.XtraEditors.XtraMessageBox.Show(IWin32Window owner, String text, String caption, MessageBoxButtons buttons, MessageBoxIcon icon)
at Test.Program.Main(String[] args)更新:通过确保在执行任何UI工作之前执行Application.Run()来解决这个问题。以这种方式启动消息循环/泵。现在我已经启动了Application.Run(),它是轻量级的、快速的。然后从splash表单中实例化主窗体,激活它并隐藏splash表单。
发布于 2010-07-09 21:00:09
据我所知,在显示任何表单之前,都需要专门调用Application.Run(),因为它启动了窗口消息循环/泵,并且基本上为UI生成了一个单独的线程。
如果不这样做,表单将无法处理消息或绘制。
我的建议是,加载主表单,并让主窗体在执行任何正常的FormLoad操作之前调用splash屏幕。如果授权失败,您可以将Application.Exit()和return从FormLoad中调用,从而在用户使用之前关闭应用程序。
编辑:请注意,主窗体在FormLoad退出后才会显示,因此在显示启动屏幕时不必担心隐藏主窗体。
编辑2:我发现了一些有价值的东西,使用ApplicationContext。您可以切换出主上下文中的哪个表单,这样就可以在初始应用程序上下文中加载启动屏幕,然后在加载之后将其交换出去。试试这个:
public class MyApplicationContext : ApplicationContext {
SplashForm splashForm;
MainForm mainForm;
public MyApplicationContext() {
splashForm = new SplashForm();
base.MainForm = splashForm;
}
public void RunApplication() {
// This will show the splash screen
ThreadPool.QueueUserWorkItem(new WaitCallback(MessageLoopThread));
// This will perform any miscellaneous loading functions
splashForm.PerformLoadingFunctions();
if (!CheckLicensing()) {
ShowErrorMessage();
Application.Exit();
return;
}
// Now load the main form
mainForm = new MainForm();
// We're done loading! Swap out our objects
base.MainForm = mainForm;
// Close our splash screen
splashForm.Close();
splashForm.Dispose();
splashForm = null;
}
private void MessageLoopThread(object o) {
Application.Run(this);
}
}然后你可以在你的主板上调用它:
static void Main() {
MyApplicationContext applicationContext = new MyApplicationContext();
applicationContext.RunApplication();
}我还没有测试过这个,但理论上应该可以。
编辑3: --我意识到这里可能存在一些线程安全问题,您可能也必须解决这些问题。看看CodeProject文章。它比我在这里做的更好。
https://stackoverflow.com/questions/3216425
复制相似问题