Est-il un non-blocage de la version de MessageBox.Afficher (ou quelque chose comme ça)?

Longtemps retardé la mise à jour

Je l'accepte MUG4N la réponse à cette question, et je veux aussi répondre à certaines des critiques qui ont été soulevées contre elle.

ChrisF dit:

...vous ne pouvez pas faire de l'INTERFACE utilisateur des appels directement à partir de threads d'arrière-plan.

C'est une déclaration générale, et n'est pas à 100% vrai. Permettez-moi simplement de souligner quelques faits:

  1. Vous pouvez réellement faire de l'INTERFACE utilisateur des appels tout ce que vous voulez si vous définissez Control.CheckForIllegalCrossThreadCalls = false. "Ack!" Je vous entends dire. "Ne pas jamais le faire!" Oui, oui, mais pourquoi? La réponse: parce que parfois cela va corrompre la mémoire.

    Les classes de contrôle dans System.Windows.Forms ne sont pas écrites pour être thread-safe, parfois, la mise à jour de threads d'arrière-plan peut corrompre la mémoire. Mais si cela ne parfois qui se passe et de ne pas toujours, ce que cela me dit que ce n'est pas la vocation de code de l'INTERFACE utilisateur soi, mais plutôt potentiellement dangereux collision de code de l'INTERFACE utilisateur qui peut causer des exceptions.

  2. Pour renforcer le point 1, considérez ceci: le "coffre-fort" façon d'invoquer code de l'INTERFACE utilisateur à partir d'un thread d'arrière-plan est de le faire à l'aide de Control.Invoke ou Control.BeginInvoke, droit? Mais ce est une INTERFACE utilisateur appel; c'est juste la de l'INTERFACE utilisateur appelez nous sommes censés faire si nous avons de la mise à jour de l'interface graphique à partir d'un non-thread GUI. Ce que je veux dire c'est, clairement, il n'est pas simplement en invoquant "toute" la méthode sur une Control objet à partir d'un filetage extérieur qui va provoquer le chaos (si c'était le cas, alors nous ne pouvions même pas appeler Invoke et nous serions coincés complètement). Encore une fois, c'est le risque de collision de séparer l'INTERFACE utilisateur des appels qui ne peuvent pas se produire en même temps qu'il va révéler destructrice.

  3. En gardant les deux points à l'esprit, demandez-vous: pourquoi serait-il dangereux pour appeler MessageBox.Show à partir d'un non-thread GUI? Complètement distincte Form est créé et affiché; ses propriétés ne sont de toute façon d'interagir avec n'importe quel autre de l'interface de l'objet; en fait, il ne peut pas être consulté n'importe où dans toute manière, sauf un: à partir du thread appelant, qui accède à son DialogResult propriété (et uniquement à l'aide de la Show de retour de la méthode de la valeur).

Se déplaçant le long. Conrad Albrecht dit:

...compte tenu de l'affirmation que Show() met en place son propre message de la pompe à Dan réf avais thème, (qui n'a pas été confirmé, mais que je ne peux pas réfuter)...

Ceci est totalement juste point (même si j'ai personnellement tenir Jared Nominale en assez haute estime de soi que je ne serais pas en général être enclin à doute ce qu'il dit). Dans tous les cas, un coup d'oeil à la MessageBox.Show méthode par Réflecteur révèle cet extrait:

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

Un autre coup d'oeil dans le Application.BeginModalMessageLoop méthode révèle ceci:

ThreadContext.FromCurrent().BeginModalMessageLoop(null);

Et ce ThreadContext.FromCurrent, tour à tour:

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

Je ne connais pas assez ces de niveau inférieur Windows constructions pour bien comprendre ce code, mais cela me semble être la preuve de ce que Jared a été dit dans la réponse que j'ai citées dans mon ancien commentaire (pour les lecteurs curieux: Ne MessageBox.Show() automatiquement marshall pour le Thread d'INTERFACE utilisateur?).

Oui. Je suis totalement en accord avec MUG4N sur celui-ci.

(Si quelqu'un peut soutenir de manière convaincante que je suis encore trompé ici, veuillez en parler. Même si je sens que j'ai fait une assez bonne affaire pour laquelle je crois MUG4N est bon, je suis bien évidemment pas certain à 100%.)


Question d'origine

Souvent vous voulez juste pour signaler à l'utilisateur que quelque chose a eu lieu, mais il n'y a vraiment pas besoin de l'entrée d'eux. Dans ce scénario, il m'arrive de voir le code comme ceci:

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

Ce code, comme nous le savons tous, les causes d'une petite fenêtre pop-up qui apparaissent avec seulement un OK bouton. Maintenant, voici la chose: ce les blocs de code (le thread d'INTERFACE utilisateur). Mais dans la grande majorité des cas, il me semble, si vous seulement ont un OK bouton, il y a très peu besoin de bloquer. (N'est-ce pas le but de blocage généralement à recevoir une entrée de l'utilisateur? Et si l'utilisateur seulement choix est "OK", et dans ce cas typique, n'est pas de blocage assez inutile?)

Évidemment, je pourrais juste écrire mon propre petit formulaire qui fait exactement ce que MessageBox.Show, sauf qu'il ne retourne rien (pas de DialogResult) et ne bloque pas. Mais je me demandais juste si quelque chose comme cela existe déjà que je ne connaissais pas.

  • L'intention d'une boîte de message est d'obtenir à l'utilisateur de décider si vous devez annuler, etc.) ou reconnaître quelque chose (si c'est juste OK) avant qu'il/elle peut continuer. - Je pense que vous devriez revoir votre conception de l'INTERFACE utilisateur si vous pensez que vous avez besoin de non-modale des boîtes de message. Qu'est-ce que le cas d'utilisation?
  • Le cas d'utilisation est en avertir l'utilisateur que quelque chose a eu lieu. Supposons que l'utilisateur active un processus au sein de l'application, puis s'éloigne de l'ordinateur pour aller à la salle de bains. Quand ils reviennent, ils veulent savoir si le processus est terminé. Pour moi, une boîte de message est la façon la plus logique de le signaler à l'utilisateur. Dans le même temps, il peut être souhaitable que cette boîte de message n'aura pas empêché l'application de continuer à exécuter d'autres processus.
InformationsquelleAutor Dan Tao | 2010-05-14