{"id":11383,"date":"2011-02-25T07:00:00","date_gmt":"2011-02-25T07:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2011\/02\/25\/why-does-waitformultipleobjects-return-error_invalid_parameter-when-all-the-parameters-look-valid-to-me\/"},"modified":"2011-02-25T07:00:00","modified_gmt":"2011-02-25T07:00:00","slug":"why-does-waitformultipleobjects-return-error_invalid_parameter-when-all-the-parameters-look-valid-to-me","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20110225-00\/?p=11383","title":{"rendered":"Why does WaitForMultipleObjects return ERROR_INVALID_PARAMETER when all the parameters look valid to me?"},"content":{"rendered":"<p>\nA customer asked for assistance with the\n<code>WaitForMultipleObjects<\/code> function:\n<\/p>\n<blockquote CLASS=\"q\">\n<p>\nI am getting\n<code>ERROR_INVALID_PARAMETER<\/code>\nwhen calling\n<code>Wait&shy;For&shy;Multiple&shy;Objects<\/code> even though\nall the parameters are valid as far as I can tell.\nI&#8217;ve narrowed it down to this simple program.\n<\/p>\n<pre>\nint main()\n{\n int i;\n HANDLE Handles[4];\n \/\/ Create the events\n for (i = 0; i &lt; 4; i++) {\n  Handles[i] = CreateEvent(NULL, FALSE, FALSE, TEXT(\"Test\"));\n  if (Handles[i] == NULL) {\n   printf(\"Failed to create event - test failed\\n\"); return 0;\n  }\n }\n \/\/ Set them all to signaled\n for (i = 0; i &lt; 4; i++) SetEvent(Handles[i]);\n \/\/ Wait for all of them - we expect this to return WAIT_OBJECT_0\n printf(\"WaitForMultipleObjects returned %d\\n\",\n        WaitForMultipleObjects(4, Handles, TRUE, INFINITE));\n return 0;\n}\n<\/pre>\n<\/blockquote>\n<p>\nFirst of all,\n<i>thank you<\/i> for narrowing the issue down to\na minimal program that illustrates the problem.\nYou&#8217;d be surprised how often a customer says,\n&#8220;I&#8217;m having problem with function&nbsp;X.\nHere&#8217;s a program that illustrates the problem.&#8221;\nAnd then attaches a huge project that doesn&#8217;t\ncompile because it is written in some\ndevelopment environment different from the one you have\non your machine.\n<\/p>\n<p>\nThe problem here is that you are passing four handles to the same\nevent to <code>Wait&shy;For&shy;Multiple&shy;Objects<\/code> with the\n<code>bWait&shy;All<\/code> parameter set to <code>TRUE<\/code>.\nThe <code>Wait&shy;For&shy;Multiple&shy;Objects<\/code> function rejects\nduplicates if you ask it to wait for all of the objects.\nWhy is that?\n<\/p>\n<p>\nWell, consider this program:\nIt creates a named auto-reset\nevent (as is &#8220;obvious&#8221; from\n<a HREF=\"http:\/\/blogs.msdn.com\/oldnewthing\/archive\/2006\/08\/28\/728349.aspx\">\nthe <code>FALSE<\/code> second\nparameter passed to <code>Create&shy;Event<\/code><\/a>)\nand stores a handle to it in <code>Handles[0]<\/code>.\nThe second through fourth calls to <code>Create&shy;Event<\/code> merely create\nnew handles to the same auto-reset event because the name matches\nan existing event.\nThe second loop sets that same event four times.\nAnd then the <code>Wait&shy;For&shy;Multiple&shy;Objects<\/code> asks to wait\nfor all of the handles to be signaled.\nBut since all four handles refer to the same object,\nit&#8217;s being asked to wait until the event has reached the state\nwhere the wait can complete four times simultaneously. (Huh?)\n<\/p>\n<p>\nRecall that <code>Wait&shy;For&shy;Multiple&shy;Objects<\/code> does not\nalter the state of any of the waited objects until the wait completes.\nIf you ask it to wait for both an event and a semaphore,\nand the event is signaled but the semaphore is not,\nthen the function will leave the event signaled while it waits\nfor the semaphore.\nOnly when all the items being waited for are signaled will the\n<code>Wait&shy;For&shy;Multiple&shy;Objects<\/code> function perform whatever\nactions are appropriate for acquiring a signaled object and return.\n<\/p>\n<p>\nOkay, so we asked it to wait on the same auto-reset event four times.\nBut that&#8217;s nonsense:\n<a HREF=\"http:\/\/blogs.msdn.com\/oldnewthing\/archive\/2006\/06\/22\/642849.aspx\">\nAn auto-reset event is just a stupid semaphore<\/a>\nwhich can have at most one token.\nBut in order for the wait to succeed, it needs four tokens.\nThat&#8217;s never going to happen, so the wait is nonsensical.\n<\/p>\n<p>\nMore generally speaking,\n<code>Wait&shy;For&shy;Multiple&shy;Objects<\/code> returns\n<code>ERROR_INVALID_PARAMETER<\/code> if you pass\n<code>bWaitAll = TRUE<\/code>\nand there are any duplicates in the handle array\n(either identical handles, or different handles to the same\nunderlying object).\nIt doesn&#8217;t try to puzzle out the objects and say,\n&#8220;Well, let me see if this is a reasonable combination of\nobjects to wait on more than once&#8221;;\nit just sees the duplicate and says\n&#8220;Forget this!&#8221;\n<\/p>\n<p>\nGoing back to the customer&#8217;s original problem:\nWe asked why they were creating four handles to the same\nobject, and what they expected when waiting for an auto-reset\nevent to have four available tokens (which it never will),\nand the customer admitted that it was just an error in their code.\nThe original version of the code used a named event and waited\non it with <code>Wait&shy;For&shy;Single&shy;Object<\/code>,\nand when they modified the code to make it support\nmultiple events, they forgot to give each event a different name.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>A customer asked for assistance with the WaitForMultipleObjects function: I am getting ERROR_INVALID_PARAMETER when calling Wait&shy;For&shy;Multiple&shy;Objects even though all the parameters are valid as far as I can tell. I&#8217;ve narrowed it down to this simple program. int main() { int i; HANDLE Handles[4]; \/\/ Create the events for (i = 0; i &lt; 4; [&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-11383","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>A customer asked for assistance with the WaitForMultipleObjects function: I am getting ERROR_INVALID_PARAMETER when calling Wait&shy;For&shy;Multiple&shy;Objects even though all the parameters are valid as far as I can tell. I&#8217;ve narrowed it down to this simple program. int main() { int i; HANDLE Handles[4]; \/\/ Create the events for (i = 0; i &lt; 4; [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/11383","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=11383"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/11383\/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=11383"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=11383"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=11383"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}