Question

J'ai un C ++ / MFC application que je dois restructurer. L'application utilisée pour traiter la plupart des données sur le thread principal, bloquant ainsi l'entrée, et maintenant je veux changer ainsi, que toutes les mises à jour sont effectuées par l'interface graphique PostMessage.

Malheureusement, je ne peux pas sembler trouver une bonne source sur la façon d'atteindre cet objectif.

En ce moment, je pense à la création d'une file d'attente prioritaire, protégée par section critique, un thread de travail (while (true)) qui traite cette file d'attente, et le mécanisme PostMessage qui envoie des pointeurs vers les données à thread principal.

Ce qui me fait peur avec cette approche est que PostMessage n'est pas garanti pour arriver au fil conducteur du tout, donc, si je comprends bien, il y a une chance de fuite de mémoire.

Le deuxième problème est qu'une autre application peut envoyer un message personnalisé à ma demande, et mon application peut essayer de déréférencer wParam ou lParam comme pointeur ce qui provoque AV.

Quelqu'un sait quelles sont les meilleures pratiques pour ces tâches?

Les données peuvent être contenu HTML pour le contrôle Web ou tout autre contenu pour les menus déroulants, listes déroulantes, etc.

Était-ce utile?

La solution

Vos messages y arriver. Je ne sais pas pourquoi vous pensez que PostMessage n'est pas garanti au travail - il est. (EDIT:! En supposant PostMessage () retourne TRUE Vérifiez vos codes de retour)

Vous voulez éviter d'utiliser une file d'attente pour communiquer des données entre les fils. Toute file d'attente qui est accessible par les deux threads doivent être protégés. Ajout de verrous durs des deux côtés sérialise votre application.

Au lieu de cela, créer une structure de données sur le tas en utilisant new qui contient vos données, puis dire à l'autre fil « I; ai données obtenu pour vous, et il est ici. » Le fil de recieving prend alors la propriété de ce pointeur de données, et est responsable de deleteing il. En procédant ainsi, il n'y a pas de serrures durs.

Maintenant, la seule astuce est de déterminer le « dire à l'autre fil » partie, mais qui est trop facile.

Si vous envoyez des données du thread de travail au thread principal, il suffit d'utiliser PostMessage():

worker_thread_proc()
{
// ..

  // Create the data object you're going to pass to the MT
  MyData* data = new MyData;
  data->some_value_ = "foo";

  // Pass it:
  PostMessage(main_wnd, WM_YOU_HAVE_DATA, reinterpret_cast<WPARAM>(data), 0);
}

... le thread principal traite ce, puis supprime les données:

MainWnd::OnYouHaveData(WPARAM wp, LPARAM)
{
  std::auto_ptr<MyData> data(reinterpret_cast<MyData*>(wp));
  my_widget->set_text(data->some_value_); // you get the idea
}

Si vous êtes inquiet au sujet des messages personnalisés de applications externes supplantation à la vôtre, vous pouvez obtenir Windows pour vous donner un ID de message unique en utilisant RegisterWindowsMessage (). - votre seul défi est de choisir ici le bon nom pour votre message

Si vos données envoi du thread principal du thread de travail, vous pouvez faire la même chose que ci-dessus, à l'exception au lieu d'utiliser PostMessage() pour envoyer les données sur le mur, vous pouvez utiliser QueueUserAPC () (en vous assurant votre thead des travailleurs est dans un état d'attente alertable - lire la remarques dans les documents liés) ou PostThreadMessage () .

EDIT:

Selon vos commentaires dans l'OP, maintenant je comprends pourquoi vous êtes préoccupé par PostMessage () ne fonctionne pas.

Oui, il y a une limite difficile à la taille de la file d'attente de messages Windows. Par défaut, il ne peut y avoir que 4 000 messages dans la file d'attente. (Paramètres de registre peuvent régler ce jusqu'à un maximum de 10 000).

Si la file d'attente est pleine, tout toPostMessage() d'appel échouera avec un code d'erreur. Lorsque vous vérifiez GetLastError () (je ne me souviens pas de quel code d'erreur retourne en ce moment), il est clair que la file d'attente des messages est pleine.

Pour ne pas sonner comme une mère poule, mais vous avez vraiment besoin de vérifier vos valeurs de retour des appels API. Mais au-delà, si vous exécutez dans le plafond le message de file d'attente, je dirais que votre demande est cassé de toute façon. Lorsque la file d'attente est pleine, votre application ne sera pas en mesure de respirer. L'écran ne sera pas la peinture, tout traitement vous sera périmé, et toutes sortes de mauvaises choses arrivent. Si cela est la situation que vous êtes, vous devrez peut-être regarder pourquoi.

Autres conseils

Utilisez deux files d'attente, l'une pour les demandes de travail allant au fil des travailleurs et un des résultats remontant au fil principal. Vous pouvez utiliser PostMessage pour réveiller le fil conducteur et lui dire de vérifier la file d'attente, mais vous aurez pas besoin de paramètres dans le message.

Je résolu un problème similaire il y a quelque temps. Je fis une file d'attente singleton pour contenir les données (ou actions) qui doivent circuler à partir de fils de fond pour le fil UI (principal). La file d'attente est protégée par une section critique. fil d'arrière-plan placerait ses données dans la file d'attente et envoyer un message. Le message ne tient pas de données, il agit comme un simple appel-up de réveil « hey, fil conducteur, regardez la file d'attente, il y a du travail pour vous ».

De cette façon, vous ne risquez pas de fuite une mémoire ou d'autres ressources; la file d'attente peut être en toute sécurité détruit toutes les données qu'il contient.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top