{"id":200,"date":"2008-02-28T16:38:02","date_gmt":"2008-02-28T15:38:02","guid":{"rendered":"http:\/\/blog.m-ri.de\/index.php\/2008\/02\/28\/afxbeginthread-versus-_beginthreadex\/"},"modified":"2008-02-23T00:47:08","modified_gmt":"2008-02-22T23:47:08","slug":"afxbeginthread-versus-_beginthreadex","status":"publish","type":"post","link":"http:\/\/blog.m-ri.de\/index.php\/2008\/02\/28\/afxbeginthread-versus-_beginthreadex\/","title":{"rendered":"AfxBeginThread versus _beginthreadex"},"content":{"rendered":"<p>Es hat sich ja mittlerweile schon herumgesprochen, dass\u00a0man <em>_beginthread(ex)<\/em> anstatt <em>CreateThread <\/em>verwenden sollte, wenn man die CRT verwendet. Die Frage ist wie steht es nun mit <em>_beginthread(ex)<\/em>\u00a0 und <em>AfxBeginThread <\/em>wenn man die MFC verwendet?<\/p>\n<p>Es ist \u00e4hnlich wie bei der CRT, es gibt auch f\u00fcr die MFC einen Thread State, der im Thread Local Storage abgelegt wird.\u00a0 Zu diesem Thread Local Storage geh\u00f6ren z.B. die tempor\u00e4ren Maps f\u00fcr die Fensterverwaltung und Maps f\u00fcr GDI-Objekt Verwaltung. Auch f\u00fcr Tooltips und diverse OLE Funktionen werden in diesem Module Thread State Daten abgelegt.<\/p>\n<p>Weiterhin werden einige Hooks gesetzt, die\u00a0notwendig werden, wenn GUI verwendet wird. Dito Aufr\u00e4umarbeiten, falls COM verwendet wird&#8230; (AfxOleInit)<br \/>\nDieser Thread Local Storage wird normalerweise beim Zerst\u00f6ren des assoziierten CWinThread wieder freigegeben. Wird die Threadfunktion verlassen oder AfxEndThread aufgerufen, dann wird der Thread Module State mit dem entsprechenden Speicher freigegeben.<\/p>\n<p>Was passiert, wenn man in einem MFC Programm einen Thread mit _beginthreadex startet und anschlie\u00dfend MFC Funktionen verwendet und dann mit _endthread den Thread terminiert?<br \/>\nWas passiert, wenn man mit AfxBeginThread einen Thread startet und ihn mit _endthread terminiert \u2753<\/p>\n<p>\u2757 Dann entsteht ein Leak, und je nach verwendeten Komponenten kein kleines \u2757<\/p>\n<p>Sollte die MFC Applikation also dynamisch Threads erzeugen, weil damit zum Beispiel Sockets \u00fcberwacht werden oder andere nette Workerthreads bedient werden, dann kann man relativ\u00a0 schnell unerfreuliches erleben.<\/p>\n<p>Es gilt also 2 Dinge zu beachten:<\/p>\n<ol>\n<li>In einem MFC Programm sollte man immer AfxBeginThread verwenden! Man geht sonst das Risiko ein, dass bei der Verwendung der ersten MFC Funktion (AfxGetResourceHandle o.\u00e4.) ein entsprechender Speicherblock angelegt wird und eben sonst nicht mehr freigegeben wird..<\/li>\n<li>Und beim Verlassen einer Threadfunktion k\u00fcmmert man sich am Besten gar nicht darum, wie der Thread gestartet wurde <img src=\"http:\/\/blog.m-ri.de\/wp-includes\/images\/smilies\/mrgreen.png\" alt=\":mrgreen:\" class=\"wp-smiley\" style=\"height: 1em; max-height: 1em;\" \/> . Man muss explizit AfxEndThread gar nicht aufrufen. Man sollte einfach alle Threadfunktionen einfach durch return verlassen. Der Thread wird dann entsprechend der Funktion, die man beim Start gew\u00e4hlt hat auch terminiert. Dann bleibt \u2013 auch bei einer \u00c4nderung der Umgebung , ob nun mit oder ohne MFC.\u00a0<\/li>\n<\/ol>\n<p>Anmerkung:<br \/>\nWarum werden diese Leaks nicht in der Debugausgabe angezeigt? Ganz einfach, weil diese Allokationen durch die MFC nicht getrackt werden. Das Speichertracking der Debugversion wird explizit f\u00fcr diese Allokationen ausgeschaltet.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Es hat sich ja mittlerweile schon herumgesprochen, dass\u00a0man _beginthread(ex) anstatt CreateThread verwenden sollte, wenn man die CRT verwendet. Die Frage ist wie steht es nun mit _beginthread(ex)\u00a0 und AfxBeginThread wenn man die MFC verwendet? Es ist \u00e4hnlich wie bei der CRT, es gibt auch f\u00fcr die MFC einen Thread State, der im Thread Local Storage &hellip; <a href=\"http:\/\/blog.m-ri.de\/index.php\/2008\/02\/28\/afxbeginthread-versus-_beginthreadex\/\" class=\"more-link\"><span class=\"screen-reader-text\">\u201eAfxBeginThread versus _beginthreadex\u201c <\/span>weiterlesen<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[30,19,4,3],"tags":[370,360,352],"class_list":["post-200","post","type-post","status-publish","format-standard","hentry","category-c","category-crt","category-mfc","category-programmieren","tag-c","tag-crt","tag-mfc"],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"http:\/\/blog.m-ri.de\/index.php\/wp-json\/wp\/v2\/posts\/200","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/blog.m-ri.de\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/blog.m-ri.de\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/blog.m-ri.de\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/blog.m-ri.de\/index.php\/wp-json\/wp\/v2\/comments?post=200"}],"version-history":[{"count":0,"href":"http:\/\/blog.m-ri.de\/index.php\/wp-json\/wp\/v2\/posts\/200\/revisions"}],"wp:attachment":[{"href":"http:\/\/blog.m-ri.de\/index.php\/wp-json\/wp\/v2\/media?parent=200"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/blog.m-ri.de\/index.php\/wp-json\/wp\/v2\/categories?post=200"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/blog.m-ri.de\/index.php\/wp-json\/wp\/v2\/tags?post=200"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}