C
C#10mo ago
Tim

❔ ✅ Why does this block the UI thread?

public async void FindWindowHandle(HandleWindowFind handleWindowFind)
{
if (!started) throw new InvalidOperationException("Process not started");
if (playerWindowHandle != IntPtr.Zero)
{
handleWindowFind(playerWindowHandle);
return;
}

var finding = IntPtr.Zero;
await Task.Run(() =>
{
while (finding == IntPtr.Zero)
{
Thread.Yield();
finding = GetWindow(_hostWindow, 5);
}
});
handleWindowFind(playerWindowHandle = finding);
}
public async void FindWindowHandle(HandleWindowFind handleWindowFind)
{
if (!started) throw new InvalidOperationException("Process not started");
if (playerWindowHandle != IntPtr.Zero)
{
handleWindowFind(playerWindowHandle);
return;
}

var finding = IntPtr.Zero;
await Task.Run(() =>
{
while (finding == IntPtr.Zero)
{
Thread.Yield();
finding = GetWindow(_hostWindow, 5);
}
});
handleWindowFind(playerWindowHandle = finding);
}
I have this function. Calling this seems to be blocking the thread that it's called from. Did I do something wrong here, or should this not block and maybe something else is causing that?
56 Replies
Tim
Tim10mo ago
What I want to accomplish is waiting for a window to exist, and then call the handleWindowFind callback
Florian Voß
Florian Voß10mo ago
there is lot of synchronous aka blocking code in this function. pretty much everything before your Task.Run() and after
Tim
Tim10mo ago
.. but that's not notable right
Florian Voß
Florian Voß10mo ago
how did you note that this blockgs the thread its called from?
Tim
Tim10mo ago
I noticed the stutter the moment this gets called Which is the exact time before for the window is created
Florian Voß
Florian Voß10mo ago
what does the synchronous handleWindowFind() do?
Tim
Tim10mo ago
It's a delegate parameter
Florian Voß
Florian Voß10mo ago
yeah I know but the function/-s stored in that delegate, what do they do? they are blocking
Tim
Tim10mo ago
It creates a new object that only assigns one value and does nothing more
Florian Voß
Florian Voß10mo ago
mhm okay how are you calling FindWindowHandle()? can you show pls
Tim
Tim10mo ago
playerManager.FindWindowHandle((IntPtr handle) => UnityHandleReady(new HandleRef(this, handle))); just like a normal function
Florian Voß
Florian Voß10mo ago
so its not an event handler, aight why is it async void? should be async Task
Tim
Tim10mo ago
what's the diff I don't want to await it cuz it's a callback
Florian Voß
Florian Voß10mo ago
async void is bad and evil and you never do it, only exception event handlers this is why its blocking tho
Tim
Tim10mo ago
Ah okie
Florian Voß
Florian Voß10mo ago
a fucntion dooesnt run asynchronouhslly just because of async. Its the await keyword that makes a func run async so have it return task and await it
Tim
Tim10mo ago
but uh wait so that await won't block?
Florian Voß
Florian Voß10mo ago
await is what makes code run asynchronously you are running this function synchronously right now
Tim
Tim10mo ago
hm allright
Florian Voß
Florian Voß10mo ago
aka blocking
Tim
Tim10mo ago
Coming from Java I had the idea that await would do the same as for example thread.join
Florian Voß
Florian Voß10mo ago
there is no equivalent in Java
Tim
Tim10mo ago
cuz it feels like await means 'wait until this is done'
Florian Voß
Florian Voß10mo ago
most similar thing would be the Future lib in java CompletableFuture is somewhat comparable to a Task in c#
Tim
Tim10mo ago
yeah fair, but then this is without the endless lambda's xD allright lemme test rq So it doesn't let me await cuz I'm calling the function from a UI thread function
Tim
Tim10mo ago
Tim
Tim10mo ago
Calling the function when a WPF control is loaded
Florian Voß
Florian Voß10mo ago
nop, it doesn't let you await because the method is not declared async
Tim
Tim10mo ago
oh wait so I don't give this the Task return? cuz it's a event but do give it async
Florian Voß
Florian Voß10mo ago
correcct, UnityIngetragtion.... should be async void because its an event handler
Tim
Tim10mo ago
hmm aight clear, that seems to work. Thank you!
Florian Voß
Florian Voß10mo ago
glad I could help
sibber
sibber10mo ago
no
Tim
Tim10mo ago
I get it now ^-^
sibber
sibber10mo ago
await means come back when this task finishes
Florian Voß
Florian Voß10mo ago
I suggest reading on TPL (Task-Parallel library), especially on TAP section (Task-based-asynchronous Pattern) https://learn.microsoft.com/en-us/dotnet/standard/asynchronous-programming-patterns/task-based-asynchronous-pattern-tap
Task-based Asynchronous Pattern (TAP): Introduction and overview - ...
Learn about the Task-based Asynchronous Pattern (TAP), and compare it to the legacy patterns: Asynchronous Programming Model (APM) and Event-based Asynchronous Pattern (EAP).
Tim
Tim10mo ago
yeah, it's weird cuz this makes the lines of code not ordered
sibber
sibber10mo ago
they are ordered thats the point of await
Florian Voß
Florian Voß10mo ago
what cyb is saying
sibber
sibber10mo ago
that you dont have to schedule continuation tasks
Tim
Tim10mo ago
No because the UI thread is executing lines while it's waiting
sibber
sibber10mo ago
like task.then(...).then(...) isnt needed
Florian Voß
Florian Voß10mo ago
the ppoint of await is to run code asnychronously but in a "synchronous fashion" which means in order but not blocking
sibber
sibber10mo ago
wdym
Tim
Tim10mo ago
I get that your own code is executed in order I mean that you could have statement 1 2 3 of your code executed and then have an await then a couple lines of UI thread code get executed and the await finishes and the next lines of your code get executed
sibber
sibber10mo ago
exactly
Tim
Tim10mo ago
So it's not entirely 'line by line' which feels odd if you don't know how it works but yeah
sibber
sibber10mo ago
yeah, but in the context of the method it is
Tim
Tim10mo ago
yup
sibber
sibber10mo ago
everything does :)
Tim
Tim10mo ago
ty for the help I gotta catch a bus ^-^ have a nice day!
sibber
sibber10mo ago
np you too :)
Florian Voß
Florian Voß10mo ago
I will point this out again just to make sure it doesnt get forgotten if your issue has been solved, dont forget to close 🙂
Tim
Tim10mo ago
Will check out the links.
Florian Voß
Florian Voß10mo ago
oh and if you're interested in how the treads get joined together when using asynchronous code, a Task stores a reference to the calling thread and continuations, which are the code that follows an await someTask call or code thats put in someTask.ContinueWith(). when it reaches Completed state it enqeues the continuations on the calling thread
Accord
Accord10mo ago
Was this issue resolved? If so, run /close - otherwise I will mark this as stale and this post will be archived until there is new activity.
Want results from more Discord servers?
Add your server
More Posts