Есть ли неблокирующая версия MessageBox.Показать (или что-то в этом роде)?

долго откладываемое обновление

я принимаю ответ MUG4N на этот вопрос, и я также хочу ответить на некоторые критические замечания, которые были подняты против него.

ChrisF сказал:

...вы не можете совершать UI-вызовы непосредственно из фоновых потоков.

это общее утверждение, и не является 100% правдой. Позвольте мне лишь указать на несколько фактов:--22-->

  1. вы можете фактически сделать UI звонки все, что вы хотите если вы устанавливаете Control.CheckForIllegalCrossThreadCalls = false. " Ack!" я слышу, как ты говоришь. "не когда-нибудь сделать это!"<!--35-- Да, да -- но почему? Ответ: потому что иногда это повредит память.

    классы управления в System.Windows.Forms не записываются, чтобы быть потокобезопасными, поэтому иногда обновление их из фоновых потоков может повредить память. Но если это только иногда происходит и не всегда, это говорит мне, что это не вызов кода пользовательского интерфейса per se, но, скорее, потенциально небезопасных столкновение кода пользовательского интерфейса, который может вызвать исключения.

  2. чтобы усилить пункт 1, Подумайте об этом: "безопасный" способ вызова кода пользовательского интерфейса из фонового потока - это сделать это с помощью Control.Invoke или Control.BeginInvoke, да? эта is вызов пользовательского интерфейса; это просто the UI вызов, который мы должны сделать, если мы обновляем GUI из потока без GUI. Я имею в виду, что, очевидно, это не просто вызов "любого" метода на Control объект из внешнего потока, который вызовет хаос (если бы это было так, то мы даже не могли бы вызвать Invoke и мы бы застряли полностью). Опять же, это потенциальное столкновение отдельных вызовов UI, которые не могут безопасно происходить одновременно, что окажется разрушительным.

  3. содержание имея в виду вышеизложенные два момента, спросите себя: почему было бы небезопасно звонить MessageBox.Show из потока без GUI? Совершенно отдельный Form создается и отображается; его свойства никоим образом не взаимодействуют с любым другим существующим объектом GUI; фактически, к нему нельзя получить доступ в любом месте на любым способом, за исключением одного: из вызывающего потока, который обращается к его DialogResult свойство (и только через Show возврат метода значение.)

двигаясь по. Конрад Альбрехт сказал:--22-->

...учитывая утверждение, что Show () устанавливает свой собственный насос сообщений в теме ref'D Дэна (который не был обоснован, но который я не могу опровергнуть)...

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

Application.BeginModalMessageLoop();
try
{
    result = Win32ToDialogResult(SafeNativeMethods.MessageBox(new HandleRef(owner, zero), text, caption, type));
}
finally
{
    Application.EndModalMessageLoop();
    UnsafeNativeMethods.ThemingScope.Deactivate(userCookie);
}

еще один взгляд в Application.BeginModalMessageLoop способ показывает это:

ThreadContext.FromCurrent().BeginModalMessageLoop(null);

и ThreadContext.FromCurrent в свою очередь:

// [Reflector shows that currentThreadContext is a ThreadStatic member. -Dan]
if (currentThreadContext == null)
{
    currentThreadContext = new Application.ThreadContext();
}
return currentThreadContext;

я недостаточно знаю об этих конструкциях окон нижнего уровня, чтобы полностью понять этот код, но мне кажется, что это доказательство того, что Джаред говорил в ответе, на который я ссылался в своем старом комментарии (для любопытных читателей: Делает MessageBox.Показывать() автоматически Маршалл в поток пользовательского интерфейса?).

так, да. Я полностью согласен с MUG4N в этом вопросе.

(если кто-нибудь может убедительно утверждать, что я все еще ошибаюсь здесь, Пожалуйста, говорите. Хотя я чувствую, что я сделал довольно хороший случай, почему я считаю, что MUG4N прав, я, очевидно, не на 100% уверен.)


исходный вопрос

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

MessageBox.Show("Something has occurred", "Something", MessageBoxButtons.OK);

этот код, как мы все знаем, вызывает небольшое всплывающее окно появится только OK. Теперь вот что: этот код блокирует (поток пользовательского интерфейса). Но в подавляющем большинстве случаев, мне кажется, если вы только есть OK кнопка, очень маленькая потребность преградить. (Не является ли цель блокировки обычно получать некоторые ввод от пользователя? И если пользователь только выбор "ОК" в этом типичном случае, не блокирует довольно бессмысленным?)

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

4 ответов


вам нужно использовать multi threading для выполнения этой задачи, в которой один поток (основной поток) будет выполнять обработку, а другой поток будет использоваться для отображения messagebox.


Как насчет добавления NotifyIcon для приложения и отображается воздушный шар наконечником? Недостатком является то, что уведомление исчезнет через короткое время, но, возможно, это лучше для ваших пользователей, если им не нужно предпринимать действия.

есть больше предложений о этот вопрос.


то, что я попытался бы назвать MessageBox функция из Win32 API напрямую, например:

using System.Runtime.InteropServices;

[DllImport("User32.dll")]
public static extern int MessageBox(int h, string m, string c, int type);

попробуйте использовать дескриптор null и тип APPLMODAL. Это может сработать.


Это старый вопрос, но тем не менее...

1) Импорт IWshShell ('Windows Script Host Object Model')

Dim wsh как новый IWshRuntimeLibrary.WshShell из WSH.Всплывающее Окно(Строка.Concat (Me.метод GetType.Полное имя, vbCrLf, _ Приложение.ExecutablePath), 0.75, "Title", MessageBoxButtons.OKCancel Или MessageBoxIcon.Вопрос)

Йенс...