@@ -56,6 +56,64 @@ namespace
5656
5757 REQUIRE (is_nta_on_mta ());
5858 }
59+
60+ IAsyncAction TestStaToStaApartmentContext ()
61+ {
62+ bool pass = false ;
63+
64+ apartment_context original;
65+
66+ // Create an STA thread and switch to it.
67+ auto controller1 = DispatcherQueueController::CreateOnDedicatedThread ();
68+ co_await resume_foreground (controller1.DispatcherQueue ());
69+
70+ // Save the COM context for the first STA thread.
71+ apartment_context context1;
72+
73+ // Create another STA thread and switch to it.
74+ auto controller2 = DispatcherQueueController::CreateOnDedicatedThread ();
75+ co_await resume_foreground (controller2.DispatcherQueue ());
76+
77+ // The first STA thread remains hung as long as this is true.
78+ bool hang_sta_1 = true ;
79+
80+ // Hang the first STA thread.
81+ controller1.DispatcherQueue ().TryEnqueue ([&] {
82+ bool hang = true ;
83+ while (hang_sta_1)
84+ {
85+ if (!WaitOnAddress (&hang_sta_1, &hang, sizeof (hang), 1000 ))
86+ {
87+ return ; // failed - timed out
88+ }
89+ }
90+ pass = true ;
91+ });
92+
93+ // Queue work to the second STA thread to unstick the first thread.
94+ // This requires that the second STA thread be available to dispatch work
95+ // after the "co_await context1" below.
96+ controller2.DispatcherQueue ().TryEnqueue ([&] {
97+ hang_sta_1 = false ;
98+ WakeByAddressAll (&hang_sta_1);
99+ });
100+
101+ // Try to switch to the first STA thread via COM context.
102+ // The first STA thread is hung, but once this thread (the second STA thread)
103+ // processes work, it will unstick the first STA thread.
104+ // This test verifies that the second STA thread does become available
105+ // to do work and is not hung waiting for the first STA thread.
106+ co_await context1;
107+
108+ REQUIRE (pass);
109+
110+ // Clean up.
111+ co_await original;
112+
113+ co_await controller1.ShutdownQueueAsync ();
114+ co_await controller2.ShutdownQueueAsync ();
115+ }
116+
59117}
60118
61119TEST_CASE (" apartment_context coverage" )
@@ -67,3 +125,8 @@ TEST_CASE("apartment_context nta")
67125{
68126 TestNeutralApartmentContext ().get ();
69127}
128+
129+ TEST_CASE (" apartment_context sta" )
130+ {
131+ TestStaToStaApartmentContext ().get ();
132+ }
0 commit comments