Подтвердить что ты не робот

Dialog MessageBox иногда скрывается за основной формой

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

Приложение написано на С#, а окна сообщений являются стандартными, например, код может быть таким же простым, как MessageBox.Show(сообщение, подпись) и сообщениями могут быть созданы с помощью основного потока пользовательского интерфейса (то есть не какого-либо фонового потока). Приложение не нужно запускать полноэкранным, но 90% наших пользователей запускают его на весь экран.

В большинстве случаев ((возможно, > 99%) сообщения отображаются правильно, и я никогда не видел, как это происходит неправильно, но я видел машину, когда она пошла не так.

Одна вещь, которую я заметил, это то, что если у вас есть приложение, которое отображает диалоговое окно, то при просмотре вашего диспетчера задач вы обычно видите только одну запись в списке приложений. Всякий раз, когда ящик сообщений скрыт, вы увидите две записи: одну для основного приложения и другую запись для этого окна сообщений.

Легко решить проблему, как только вы знаете, что произошло, но некоторые из наших нетехнических пользователей запутались в этом и в конечном итоге отключили свои компьютеры. (И те, кто использует Remote Desktop, еще более запутаны, если это не решает проблему).

Я не думаю, что это связано с операционной системой, поскольку я видел это в Vista, и мне сказали, что это также происходит в терминальном сеансе на сервере Windows 2003.

Знаете ли вы, почему это происходит, и что еще важнее, если что-то можно сделать, чтобы избежать этого?

4b9b3361

Ответ 1

Некоторые перегрузки метода MessageBox.Show() принимают в качестве первого аргумента параметр IWin32Window. Если вы передадите форму в качестве первого аргумента, это должно помешать этому.

Ответ 2

Является ли это всегда одним и тем же полем сообщений (для одного и того же сообщения?), которое появляется в той же форме?

В идеале вы должны попытаться найти способ воспроизвести проблему по своему усмотрению или, по крайней мере, автоматически. Это упростит вашу отладку, и вы можете быть уверены, что ваши будущие изменения исправят ошибку, а не придется ждать нескольких недель для отзывов ваших пользователей.

Если это всегда одно и то же сообщение и в том же окне, в результате одного и того же действия, и если вызов MessageBox можно легко запускать с точки зрения пользователя, и если ваш пользовательский интерфейс является относительно стандартным, вы можете автоматизировать пользовательский интерфейс с AutoIT script и запустить его в цикле до тех пор, пока не возникнет проблема.

И/или вы могли бы создать "отладочную" -стройку своих приложений, которую вы могли бы дать ее некоторым пользователям (предпочтительно тем, которые чаще всего сталкиваются с проблемой), которые будут писать содержимое StackFrame объект в файл журнала или что-то подобное каждый раз перед вызовом MessageBox (вы можете создать обертку вокруг MessageBox, чтобы сделать это проще).

Затем, когда у одного из ваших пользователей возникнет проблема, вы можете посмотреть файл журнала и посмотреть, откуда он взялся (файл исходного кода, строка, стек вызовов и т.д.). Вы также можете сравнить это с журналами от других пользователей и посмотреть, если каждый раз MessageBox приходит из того же места или изменяется. Это покажет вам, откуда вызывается проблемный MessageBox и где.

Могут быть более простые решения (особенно если ваше приложение имеет множество сборок) с участием некоторого отладчика .Net, который вы присоедините к своему приложению, когда возникнет проблема, чтобы увидеть стек вызовов и т.д., но я сделал это только с собственными приложениями (с использованием OllyDbg) до сих пор, а не .Net. Другие могут еще больше расширить эту идею...

Ответ 3

Подтвердите проблему. Что мы делаем, чтобы исправить это следующее:

  1. Запустите новую задачу и отобразите окно сообщения
  2. В главном потоке пользовательского интерфейса, пока задача еще выполняется - подождите в цикле, который выполняет DoEvents. Что-то вроде этого

ОБНОВЛЕНО 2015-12-17. Воспроизводится проблема вчера. Чтобы сделать репо в моем случае - сверните приложение, всплывающее окно "подождите" (в нашем случае это происходит после некоторого простоя), затем в панели задач нажмите на значок основного приложения. Это "скрывает" всплывающее окно, поэтому вывести его на экран невозможно. Код ниже был проверен и решает проблему. Но я до сих пор не понимаю, что/почему это происходит.

    private static DialogResult ShowMessageBox(
        string message, 
        string caption, 
        MessageBoxButtons buttons, 
        MessageBoxIcon icon)
    {

        var showMessageBoxTask = new Task<DialogResult>(() =>
        {
            var form = new Form() {TopMost = true};

            var result = MessageBox.Show(
                form,
                PrepareMessage(message),
                caption,
                buttons,
                icon);

            form.Dispose();

            return result;
        });

        showMessageBoxTask.Start();

        while (!showMessageBoxTask.IsCompleted && !showMessageBoxTask.IsFaulted)
        {
            Application.DoEvents();
        }

        return showMessageBoxTask.Result;
    }

Ответ 4

Вы говорите: "ящики сообщений могут быть созданы с помощью основного потока пользовательского интерфейса", который, как я полагаю, означает, что они не всегда создаются основным потоком пользовательского интерфейса. Ваша проблема звучит так: MessageBox.Show иногда вызывается из другого потока.

Ответ 5

В родительской форме добавьте это до MessageBox.Show():

this.TopMost = false;