Éviter l'étiquette "(ne répondant pas)" dans les fenêtres lors du traitement de beaucoup de données en une seule bosse
J'ai parfois besoin de traiter une grande quantité de données d'un paquet sur le réseau, qui prend suffisamment longue pour que lorsque l'utilisateur essaie d'interagir avec l'application windows ajoute le "(ne Répond Pas)" chaîne de caractères pour le titre de la fenêtre. J'en suis conscient, c'est parce que le traitement est effectué à l'intérieur d'un appel pour gérer un message (d'une certaine façon de la pile) et donc le blocage de la pompe de message. Je sais aussi le moyen idéal pour traiter cette question est de traiter les données de manière asynchrone dans un thread séparé de sorte que la pompe continue de fonctionner, cependant, c'est une GRANDE application de bureau qui est mono-thread de la tête aux pieds et en toute sécurité filer cette transformation n'est pas possible dans notre temps.
Donc, avec cela à l'esprit, est-il, par hasard, un moyen pour que je puisse au moins d'éviter le "pas de réponse" surnom (qui pour la plupart des utilisateurs se lit comme "s'est écrasé") en disant windows mon application est sur le point d'être occupé avant de commencer le travail? Je crois qu'il y est quelque chose le long de ces lignes au moment de répondre à une demande de la fermer, on peut se demander de windows pour plus de temps pour l'éviter en proclamant que votre pas de "clôture en temps opportun"
J'ajouterais que c'est un C++ MFC application.
source d'informationauteur Foo42
Vous devez vous connecter pour publier un commentaire.
Je ne pense pas que l'API Windows peut vous aider ici.
Sinon, comment sur l'affichage d'une boîte de dialogue avec une barre de progression et le faire fonctionner dans un thread séparé?
Un texte comme "Cette opération peut prendre une demi-heure" sur la boîte de dialogue peut être approprié.
Ok, tout d'abord je upvoted Frédéric post parce qu'il aime ou pas, le deuxième fil est probablement la meilleure façon d'aller.
Toutefois, si vous avez vraiment ne voulez pas aller en bas de cette route, vous pouvez manuellement la pompe de la file d'attente de messages au sein de vos applications à l'intérieur de la boucle. Quelque chose comme ceci;
C'est en fait un morceau de code que j'ai utilisé avant de réécrire quelque chose de similaire comme un sujet séparé. Fondamentalement, j'ai un oeil à la file d'attente, filtrer les messages indésirables, et de les poster sur le reste. Il fonctionne dans une certaine mesure, mais il a provoqué quelques effets secondaires désagréables, d'où la réécriture.
Vous n'avez pas à faire quoi que ce soit avec les messages de PeekMessage. Appelez simplement PeekMessage, vous n'avez même pas pour enlever quoi que ce soit à partir de la file d'attente ou de processus. Tant qu'elle est appelée à chaque 5 secondes, il sera la cause de windows pour penser le processus est toujours réactive.
Une alternative idée est d'avoir un processus/thread qui apparaîtra dans la barre de notification et d'informer l'utilisateur que le processus est occupé d'attente pour une opération interne à compléter. Vous verrez cela dans les dernières versions de Visual Studio, SQL Server Management Studio, etc.
Si vous bifurquer un fil, vous êtes probablement inquiet à propos de quelque autre action de l'utilisateur qui se passe, qui peuvent dépendre du résultat de l'opération longue à exécuter (ouais, la simultanéité). Afin d'étendre sur ce Fredrick dit, si vous ne le spin-off d'un nouveau fil de discussion et de mettre en place une barre de progression, vous pouvez verrouiller le focus sur la barre de progression pour arrêter un utilisateur d'interagir avec le reste de l'application. Cela devrait être suffisant pour mettre en œuvre un vraiment simple deuxième thread sans vraiment avoir à se soucier de la simultanéité parce que vous êtes essentiellement de verrouillage sur le reste de l'application par la désactivation de l'interaction de l'utilisateur.
Vous aurez besoin de façon à le combiner le traitement avec traitement des messages d'une certaine manière. Si les threads sont hors de question, vous voudrez peut-être regarder à scinder le traitement en plusieurs phases. Une façon de le faire est d'effectuer un traitement quand vous recevez le paquet, puis de poster un message à la demande en disant: "continuer à traiter ici". Lorsque l'application reçoit le "poursuivre le traitement ici." s'affiche, il va faire plus de traitement, et d'envoyer un autre "poursuivre le traitement ici." s'affiche ou d'en finir.
Il ya un couple de considérations:
Je ne sais pas si ce serait faisable dans la conception de votre application, mais il serait un moyen de résoudre le problème.
Win32 a une méthode pour cela dans
user32.dll
.DisableProcessWindowGhosting()
En outre comportement documenté, j'ai aussi vérifié ici (dans une application C#) que cette Win32 appel empêche également la ne Répond Pas étiquette apparaissant sur la fenêtre désirée.
J'ai trouvé ceci par le C# réponse à la question similaire ici: https://stackoverflow.com/a/15380821/29152.
Si vous êtes réticents à frayer un thread de travail, mais vous pouvez rompre les tâches en cours d'exécution en petites parties, vous pouvez faire le traitement dans MFC
CWinApp::OnIdle
. Cette fonction est appelée à partir de l'intérieur de la pompe de message en boucle à chaque fois qu'il y a pas de Fenêtres de messages en attente. Tant que le travail que vous faites dans chaqueOnIdle
appel est suffisamment courte, vous gardez la réactivité de votre application.En supposant que c'est le traitement des données personnelles qui est de prendre tout le temps, et de ne pas le recevoir (et vous êtes sérieux au sujet d'éviter un thread qui est bien IMOHO) des données vous pouvez:
La nature de la boîte de dialogue modale gardera vous êtes à la demande "responsive", avec un minimum d'interruption ou changement dans la façon dont l'application fonctionne déjà. La réentrance peut-être un problème avec modal boucles, surtout si l'un de ce qui est impliqué avec un message WM_PAINT. (quiconque a déjà affirmer à l'intérieur de la peinture de code? de bons moments, de bons moments...)
La boîte de dialogue pourrait même avoir un bouton annuler si vous le souhaitez.
J'ai rencontré le exacte même problème.
Depuis je n'envisager d'autres réponses attrayant/simple j'ai décidé de poster cette.
Courte description et contexte:
Je suis de l'enregistrement des données à partir d'une grille dans une base de données, et ce processus peut prendre un certain temps. J'ai donc modifié la méthode d'enregistrement d'une méthode asynchrone et avait le même problème.
Alors je suis venu avec une solution simple:
Lors du démarrage de la méthode asynchrone, j'ai désactiver la boîte de dialogue principale.
Cela évite à l'utilisateur d'interagir avec la boîte de dialogue principale (comme le début d'un autre processus d'enregistrement de ce qui pourrait entraîner des milliers de messages d'erreur SQL si je n'aurais pas de vérifier si le processus d'enregistrement est déjà en cours d'exécution...)
Lorsque le processus de sauvegarde est terminé, je l'ai ré-activer la boîte de dialogue principale.
Fonctionne comme un charme, j'espère que cette aide
Une façon de surmonter votre application ne répond plus, vous devez dire à l'application de traiter des messages de windows. Lorsque vous êtes dans votre boucle, vous pouvez appeler