0

I know that forms should be made on an STA thread because of the way forms work. But I assumed I can make a form object in any thread as long as I actually 'run' it in an STA thread, like with form.Show(), form.ShowDialog() or Application.Run(form), so its message loop is running on an STA thread.

If I run this code:

public async Task Test1() {
    Console.WriteLine($"Threadpool: {Thread.CurrentThread.IsThreadPoolThread}");

    Console.WriteLine("Start");
    var form = new TextForm();     // Some basic form
    Console.WriteLine("Middle");
    await Task.Yield();            // This await never continues if run on threadpool
    Console.WriteLine("End");
}

...then on an STA thread the code will reach 'End' immediately, but if run on a threadpool thread the code never reaches 'End'.

SirVeggie
  • 31
  • 3
  • 1
    *make a form object in any thread as long as I actually 'run' it in an STA thread* - Specifically, controls must only be accessed by the thread that created them – Caius Jard Jan 16 '21 at 15:31
  • A Form class has a built in block so it never closes until a user closes the form. – jdweng Jan 16 '21 at 15:37
  • Thats because the UI thread has a SynchronizationContext bound to that thread, which ensures that await will continue on the UI thread. The Threadpool has not. So I think is has something to do with that – Jeroen van Langen Jan 16 '21 at 15:53
  • `Application.Run()` creates a new [ApplicationContext](https://learn.microsoft.com/en-us/dotnet/api/system.windows.forms.applicationcontext), using the internal [Threadcontext](https://referencesource.microsoft.com/#System.Windows.Forms/winforms/Managed/System/WinForms/Application.cs,2315) class [FromCurrent()](https://referencesource.microsoft.com/#System.Windows.Forms/winforms/Managed/System/WinForms/Application.cs,3044) method. – Jimi Jan 16 '21 at 16:36
  • Example running a (functional) Form in a Console app: [Adding MenuItems to Contextmenu for a TrayIcon in a Console app](https://stackoverflow.com/a/65048753/7444103) – Jimi Jan 16 '21 at 16:43
  • 1
    The call to `new TextForm()` implicitly creates a new synchronization context for the current thread, replacing the one that was there. That synchronization context requires a call _in that thread_ to `Application.Run()` for it to dispatch any continuations. You never call `Application.Run()`, so the continuation can never run. See duplicate. – Peter Duniho Jan 16 '21 at 18:37

0 Answers0