I have run into some legacy code Winforms code that basically does this...
private static bool _connected = false;
private static bool _closing = false;
static void Main(string[] args)
{
// Stuff
ThreadPool.QueueUserWorkItem(ThreadProc, null);
// More stuff
while (!_closing)
{
if (_connected)
{
break;
}
// Do stuff
Application.DoEvents();
Thread.Sleep(100);
// Do stuff
}
if (_connected)
{
// Finally...
Application.Run(new MyForm());
}
}
private static void ThreadProc(object obj)
{
while (!_closing)
{
// Stuff
if (!Method2())
{
// Error
_closing = true;
return;
}
else
{
/// Success
break;
}
}
_connected = true;
}
private static async Task<SomeData> Method1()
{
// There is a splash screen that gets displayed so we are
// waiting for it to be available
while (Application.OpenForms.Count == 0) Thread.Sleep(100);
// So this gets run on the Windows GUI thread
SomeData result = await (Application.OpenForms[0].Invoke(new Func<Task<SomeData>>(() => { SomethingAsync())));
return result;
}
private static bool Method2()
{
TaskAwaiter<SomeData> awaiter = Method1().GetAwaiter();
while (!awaiter.IsCompleted)
{
// This appears to be why this code is done this way...
// to not block Windows events while waiting.
Application.DoEvents();
Thread.Sleep(100);
}
var SomeData = awaiter.GetResult();
if (result == null) { return false; } // error
// do something with result
return true;
}
I have read up a bit on the negatives on using GetAwaiter().GetResult()
and I'm searching for a better solution. I believe the reason this was done this way was so application events didn't block while Method1()
executes since we are checking IsCompleted
on the awaiter and once it is complete, we then get the result.
Is this a legit usage of GetAwaiter()
and GetResult()
or is there a better solution?
The above legacy code works and I am unsure as to whether this is a "good" solution to the problem or is a timebomb waiting to happen.
Clarification: The Method2
is called from a thread that was created using ThreadPool.QueueUserWorkItem() from inside the static Main()
method, before the Application.Run()
which is not called until after the thread terminates and is thus called on the same thread that entered the static Main()
method. I have attempted to update the code with a simplified version of what I am dealing with that showcases the additional thread and when Application.Run() is invoked.
Purpose The purpose appears to be that when the application runs, it creates a thread that calls Method1 which basically does user login/authentication. Once authenticated, it attempts to connect to a server process using a JWT. The Main() thread is looping to wait for the connection thread to either succeed or error out while also calling Application.DoEvents(). I don't quite understand the purpose of the second thread.