Comment ouvrir un formulaire dans un thread et le forcer à rester ouvert
Je suis toujours avoir des problèmes à trouver comment créer des winforms dans un autre thread d'INTERFACE utilisateur qui j'ai discuté ici.
En essayant de comprendre ce que j'ai écrit la suite de programme de test simple. Je veux simplement ouvrir un formulaire sur un thread séparé nommé "thread d'INTERFACE utilisateur" et de garder le thread en cours d'exécution tant que le formulaire est ouvert, tout en permettant à l'utilisateur d'interagir avec le formulaire (filage est de la triche). Je comprends pourquoi le ci-dessous échoue et le fil se ferme immédiatement, mais je suis pas sûr de ce que je dois faire pour résoudre le problème.
using System;
using System.Windows.Forms;
using System.Threading;
namespace UIThreadMarshalling {
static class Program {
[STAThread]
static void Main() {
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
var tt = new ThreadTest();
ThreadStart ts = new ThreadStart(tt.StartUiThread);
Thread t = new Thread(ts);
t.Name = "UI Thread";
t.Start();
Thread.Sleep(new TimeSpan(0, 0, 10));
}
}
public class ThreadTest {
Form _form;
public ThreadTest() {
}
public void StartUiThread() {
_form = new Form1();
_form.Show();
}
}
}
Yep, c'est juste de Microsoft à défaut de bien réfléchir à autre chose qu'une boîte de dialogue unique et seul thread une fois de plus. Comme les solutions ci-dessous vous dis que vous pouvez commencer un message séparé de la pompe, mais il n'existe aucun moyen pratique de lancer ce à partir du thread GUI, donc il n'y a aucun moyen de faire la deuxième forme se comporter comme un dialogue non modale.
Pour être juste, la question est de savoir à partir de 4 ans et portant sur une période de 12 ans de la technologie 🙂
Ouais je sais, mais mis à part le fait que même il y a 12 ans les gens voulaient, et ce, sans même le regarder, j'va miser une grosse somme que la situation n'a pas changé dans la révision/les nouvelles API de MME
Je ne pense pas que c'est juste, je n'ai jamais eu trop profondément dans WPF, mais ce que j'ai fait, ne semblent pas souffrir de ces problèmes (et dans beaucoup de façons, WPF a été une plus grande maturité de l'INTERFACE utilisateur de la technologie que de l'HTML). Le nouveau javascript Isu je pense que travailler sur un nœud de style boucle d'événements, donc je ne pense pas que le thread d'interface utilisateur est même un problème. Pour tous ses nombreux défauts, Microsoft ne mérite un certain crédit pour la façon dont ses outils de dev ont évolué.
Pour être juste, la question est de savoir à partir de 4 ans et portant sur une période de 12 ans de la technologie 🙂
Ouais je sais, mais mis à part le fait que même il y a 12 ans les gens voulaient, et ce, sans même le regarder, j'va miser une grosse somme que la situation n'a pas changé dans la révision/les nouvelles API de MME
Je ne pense pas que c'est juste, je n'ai jamais eu trop profondément dans WPF, mais ce que j'ai fait, ne semblent pas souffrir de ces problèmes (et dans beaucoup de façons, WPF a été une plus grande maturité de l'INTERFACE utilisateur de la technologie que de l'HTML). Le nouveau javascript Isu je pense que travailler sur un nœud de style boucle d'événements, donc je ne pense pas que le thread d'interface utilisateur est même un problème. Pour tous ses nombreux défauts, Microsoft ne mérite un certain crédit pour la façon dont ses outils de dev ont évolué.
OriginalL'auteur George Mauer | 2008-10-03
Vous devez vous connecter pour publier un commentaire.
Sur un nouveau thread, Application d'appel.Exécutez le passage de la forme de l'objet, cela va rendre le fil d'exécuter sa propre boucle de message lorsque la fenêtre est ouverte.
Alors que vous pouvez appeler .Rejoindre sur ce thread pour faire de votre thread principal d'attendre jusqu'à ce que le thread de l'INTERFACE utilisateur a été résilié, ou utiliser une astuce similaire à attendre que le thread au complet.
Exemple:
OriginalL'auteur Lasse Vågsæther Karlsen
Je pense que votre problème est avec cette pensée: "ouvrir un formulaire sur un thread séparé nommé "thread d'INTERFACE utilisateur'"
La façon dont windows fonctionne, c'est comme cela (plz note Vista peut changer certains de ces réalités):
Il est important de thread appelé le "Thread Principal" ou la "Thread d'INTERFACE utilisateur". Ce fil est celui qui est le processus les messages de windows, comme "hey la souris cliqué sur ce pixel."
Ces messages dans une file d'attente, et le thread principal traite quand il n'est pas occupé à faire autre chose.
Donc, si vous faites un appel de fonction foo() sur le thread principal, si elle prend beaucoup de temps, pas de fenêtres messages sont traités au cours de cette époque, et donc aucune interaction de l'utilisateur peut se produire.
Le thread principal fournit également l'INTERFACE utilisateur sur l'écran, donc long à l'exécution de foo() va également arrêter votre application de la peinture.
Tous les autres threads en plus de ce saint et spécial thread principal sont grognement de threads de travail. Ces threads de travail peut faire des choses, mais ils ne peuvent pas interagir directement avec l'interface utilisateur.
Cette réalité pose deux problèmes:
Descendre LE THREAD PRINCIPAL: Puisque vous ne voulez pas long à l'exécution de foo() pour mettre fin à toutes les interactions avec l'utilisateur, vous avez besoin d'expédier ce travail à un thread de travail.
DE retrouver LE THREAD PRINCIPAL: Lorsque l'exécution de foo() se termine, vous voulez sans doute pour avertir l'utilisateur de faire quelque chose dans l'INTERFACE utilisateur, mais vous ne pouvez pas le faire dans un thread de travail, de sorte que vous besoin de "revenir" pour le thread principal.
Donc je crois que votre problème dans le programme ci-dessus est très général: Votre objectif est incorrect, car il n'est pas censé être possible d'appeler _form.Show() dans n'importe quel thread, mais le saint-thread principal.
OriginalL'auteur rice
OriginalL'auteur CheeZe5
Vous ne pouvez pas ouvrir un GUI forme dans n'importe quel thread, parce qu'il va manquer un message de la pompe.
Vous devez explicitement démarrer une pompe de message dans ce thread en invoquant l'Application.Run() dans une méthode de fil. Une autre option est d'appeler une fonction DoEvents() dans une boucle, si vous avez besoin de faire quelque chose d'autre, parce que, après l'Application.Run() du thread attente d'un utilisateur pour fermer un formulaire dans ce point de l'exécution.
OriginalL'auteur Nenad Dobrilovic
Je pense que tout le qualifiant de ShowDialog au lieu de Montrer de l'aide. Le problème semble être que le thread se termine juste après l'appel de Montrer, après que le Formulaire d'obtenir des ordures collectées. ShowDialog interrompt le fil, mais toujours exécuter forme-événements sur elle de sorte que le thread continuera à fonctionner jusqu'à ce que le formulaire est fermé.
Normalement, je devrais le faire dans l'autre sens. Exécutez le formulaire sur le fil de départ et de commencer threads d'arrière-plan lorsque vous souhaitez commencer à long exécution de tâches de fond.
J'ai aussi lu votre autre question, mais ne parvenait pas à comprendre ce que vous essayez de faire. MVP-architecture ne vous obligent pas à faire fonctionner votre entreprise, la logique sur des threads différents. Multi threading est dur à faire donc je ne pourrais que l'utilisation de plusieurs threads si j'ai vraiment besoin d'eux.
OriginalL'auteur Mendelt
Au lieu de l'appeler show() sur le formulaire qui s'exécutent sur le formulaire, puis il suffit de fermer à la fin de l'exécution du thread au sein de la fonction StartUiThread(), vous pouvez verrouiller le fil jusqu'à ce que le formulaire est arrêté à l'intérieur de la méthode que vous êtes tout simplement le verrouillage de l'autre thread. Ex:
Ce qui va causer le nouveau fil d'attendre jusqu'à ce que la boîte de dialogue est fermée. Je ne sais pas si cela va résoudre vos problèmes, mais il a résolu le mien.
OriginalL'auteur Oli4