{"id":33843,"date":"2005-10-10T10:00:09","date_gmt":"2005-10-10T10:00:09","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2005\/10\/10\/thread-affinity-of-user-interface-objects-part-1-window-handles\/"},"modified":"2005-10-10T10:00:09","modified_gmt":"2005-10-10T10:00:09","slug":"thread-affinity-of-user-interface-objects-part-1-window-handles","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20051010-09\/?p=33843","title":{"rendered":"Thread affinity of user interface objects, part 1: Window handles"},"content":{"rendered":"<p><P>\nDifferent objects have different thread affinity rules,\nbut the underlying principles come from 16-bit Windows.\n<\/P>\n<P>\nThe most important user interface\nelement is of course the window.\nWindow objects have thread affinity.\nThe thread that creates a window is the one with which\nthe window has an inseparable relationship.\nInformally, one says that the thread &#8220;owns&#8221; the window.\nMessages are dispatched to a window procedure only\non the thread that owns it,\nand generally speaking,\nmodifications to a window should be made only from the\nthread that owns it.\nAlthough the window manager permits any thread to\naccess such things as window properties, styles,\nand other attributes such as the window procedure,\nand such accesses are thread safe from the window manager&#8217;s\npoint of view,\nload-modify-write sequences should typically be restricted\nto the owner thread.\nOtherwise you run into race conditions such as the following:\n<\/P>\n<PRE>\nwpOld = (WNDPROC)GetWindowLongPtr(hwnd, GWLP_WNDPROC);\nSetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR)newWndProc);<\/p>\n<p>LRESULT CALLBACK newWndProc(&#8230;)\n{\n &#8230; CallWindowProc(wpOld, &#8230;); &#8230;\n}\n<\/PRE>\n<P>\nIf modifications to the window procedure are made carelessly\nfrom any thread, then between the first two lines,\na second thread may change the window procedure of the window,\nresulting in <CODE>newWndProc<\/CODE> passing the wrong\n&#8220;previous&#8221; window procedure to <CODE>CallWindowProc<\/CODE>.\n<\/P>\n<P>\nWhy, then, does Windows even allow a non-owner thread from\nchanging the window procedure in the first place?\nBecause, as we all know, 16-bit Windows was a co-operatively\nmulti-tasked system,\nwhich means that one thread could do anything it wanted\nsecure in the knowledge that no other thread would interrupt it\nuntil it explicitly relinquished control of the CPU.\nTherefore, the above code sequence was safe in 16-bit Windows.\nAnd for compatibility reasons, the code continues to be legal,\neven though it isn&#8217;t safe any more.\n(Note, however, that in an attempt to limit the scope of the\ndamage, the window manager allows only threads in the process\nthat owns the window to change the window procedure.\nThis is a reasonable limitation since separate address spaces\nmean that function addresses in other processes are meaningless\nin the process that owns the window anyway.)\n<\/P>\n<P>\nNext time, a look at device contexts.\n<\/P><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Different objects have different thread affinity rules, but the underlying principles come from 16-bit Windows. The most important user interface element is of course the window. Window objects have thread affinity. The thread that creates a window is the one with which the window has an inseparable relationship. Informally, one says that the thread &#8220;owns&#8221; [&hellip;]<\/p>\n","protected":false},"author":1069,"featured_media":111744,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[25],"class_list":["post-33843","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>Different objects have different thread affinity rules, but the underlying principles come from 16-bit Windows. The most important user interface element is of course the window. Window objects have thread affinity. The thread that creates a window is the one with which the window has an inseparable relationship. Informally, one says that the thread &#8220;owns&#8221; [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/33843","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/users\/1069"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/comments?post=33843"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/33843\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media\/111744"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media?parent=33843"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=33843"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=33843"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}