Почему я получаю исключение «Объект используется в другом месте»? - PullRequest
0 голосов
/ 10 июля 2010

У меня есть приложение C # WinForms.Это исключение выдается в методе static void Main (), когда перед запуском основной формы пользовательского интерфейса отображается DevExpress XtraMessageBox.Ниже приведен код (упрощенно):

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, при вызове к нему на самом деле выдается:Это воспроизводимо на определенной машине, но как только я добавляю 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)

Обновление: Я решил ее, убедившись, что Application.Run () выполняется перед выполнением любой работы пользовательского интерфейса.Таким образом, цикл сообщений / насос запускается.Теперь у меня есть Application.Run (), запускающий всплывающую форму, которая является легкой и быстрой.Затем внутри формы-заставки я создаю основную форму, активирую ее и скрываю форму-заставку.

1 Ответ

1 голос
/ 10 июля 2010

Насколько я понимаю, Application.Run() должен быть специально вызван, прежде чем показывать какую-либо форму, так как он запускает цикл сообщений / насос окна и в основном порождает отдельный поток для пользовательского интерфейса.

Если вы этого не сделаете, форма не сможет обрабатывать сообщения или рисовать.

Мое предложение заключается в том, чтобы загрузить основную форму и заставить основную форму вызывать заставку, прежде чем она выполнит какую-либо из ее операций.нормальный FormLoad материал.Если лицензирование не удается, вы можете вызвать 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 статьи .Это лучше, чем то, что я сделал здесь.

...