首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么我会得到"Object目前正在其他地方使用“的异常?

为什么我会得到"Object目前正在其他地方使用“的异常?
EN

Stack Overflow用户
提问于 2010-07-09 20:45:21
回答 1查看 3.1K关注 0票数 0

我有一个C# WinForms应用程序。当启动主UI表单之前显示DevExpress XtraMessageBox时,将在静态void ()方法中抛出此异常。以下是代码(简化):

代码语言:javascript
复制
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控件,但实际上在调用:

代码语言:javascript
复制
System.Drawing.Graphics.get_PageUnit()

异常不会始终抛出。它可以在特定的机器上复制,但是一旦我在异常之前添加了一个MicroSoft MessageBox.Show()来显示调试信息,那么我就不再获得异常。下面是堆栈跟踪:

代码语言:javascript
复制
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表单。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2010-07-09 21:00:09

据我所知,在显示任何表单之前,都需要专门调用Application.Run(),因为它启动了窗口消息循环/泵,并且基本上为UI生成了一个单独的线程。

如果不这样做,表单将无法处理消息或绘制。

我的建议是,加载主表单,并让主窗体在执行任何正常的FormLoad操作之前调用splash屏幕。如果授权失败,您可以将Application.Exit()returnFormLoad中调用,从而在用户使用之前关闭应用程序。

编辑:请注意,主窗体在FormLoad退出后才会显示,因此在显示启动屏幕时不必担心隐藏主窗体。

编辑2:我发现了一些有价值的东西,使用ApplicationContext。您可以切换出主上下文中的哪个表单,这样就可以在初始应用程序上下文中加载启动屏幕,然后在加载之后将其交换出去。试试这个:

代码语言:javascript
复制
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);
    }
}

然后你可以在你的主板上调用它:

代码语言:javascript
复制
static void Main() {
    MyApplicationContext applicationContext = new MyApplicationContext();
    applicationContext.RunApplication();
}

我还没有测试过这个,但理论上应该可以。

编辑3: --我意识到这里可能存在一些线程安全问题,您可能也必须解决这些问题。看看CodeProject文章。它比我在这里做的更好。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/3216425

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档