C
C#2y 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
TimOP2y ago
What I want to accomplish is waiting for a window to exist, and then call the handleWindowFind callback
Thalnos
Thalnos2y ago
there is lot of synchronous aka blocking code in this function. pretty much everything before your Task.Run() and after
Tim
TimOP2y ago
.. but that's not notable right
Thalnos
Thalnos2y ago
how did you note that this blockgs the thread its called from?
Tim
TimOP2y ago
I noticed the stutter the moment this gets called Which is the exact time before for the window is created
Thalnos
Thalnos2y ago
what does the synchronous handleWindowFind() do?
Tim
TimOP2y ago
It's a delegate parameter
Thalnos
Thalnos2y ago
yeah I know but the function/-s stored in that delegate, what do they do? they are blocking
Tim
TimOP2y ago
It creates a new object that only assigns one value and does nothing more
Thalnos
Thalnos2y ago
mhm okay how are you calling FindWindowHandle()? can you show pls
Tim
TimOP2y ago
playerManager.FindWindowHandle((IntPtr handle) => UnityHandleReady(new HandleRef(this, handle))); just like a normal function
Thalnos
Thalnos2y ago
so its not an event handler, aight why is it async void? should be async Task
Tim
TimOP2y ago
what's the diff I don't want to await it cuz it's a callback
Thalnos
Thalnos2y ago
async void is bad and evil and you never do it, only exception event handlers this is why its blocking tho
Tim
TimOP2y ago
Ah okie
Thalnos
Thalnos2y 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
TimOP2y ago
but uh wait so that await won't block?
Thalnos
Thalnos2y ago
await is what makes code run asynchronously you are running this function synchronously right now
Tim
TimOP2y ago
hm allright
Thalnos
Thalnos2y ago
aka blocking
Tim
TimOP2y ago
Coming from Java I had the idea that await would do the same as for example thread.join
Thalnos
Thalnos2y ago
there is no equivalent in Java
Tim
TimOP2y ago
cuz it feels like await means 'wait until this is done'
Thalnos
Thalnos2y ago
most similar thing would be the Future lib in java CompletableFuture is somewhat comparable to a Task in c#
Tim
TimOP2y 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
TimOP2y ago
Tim
TimOP2y ago
Calling the function when a WPF control is loaded
Thalnos
Thalnos2y ago
nop, it doesn't let you await because the method is not declared async
Tim
TimOP2y ago
oh wait so I don't give this the Task return? cuz it's a event but do give it async
Thalnos
Thalnos2y ago
correcct, UnityIngetragtion.... should be async void because its an event handler
Tim
TimOP2y ago
hmm aight clear, that seems to work. Thank you!
Thalnos
Thalnos2y ago
glad I could help
sibber
sibber2y ago
no
Tim
TimOP2y ago
I get it now ^-^
sibber
sibber2y ago
await means come back when this task finishes
Thalnos
Thalnos2y 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
TimOP2y ago
yeah, it's weird cuz this makes the lines of code not ordered
sibber
sibber2y ago
they are ordered thats the point of await
Thalnos
Thalnos2y ago
what cyb is saying
sibber
sibber2y ago
that you dont have to schedule continuation tasks
Tim
TimOP2y ago
No because the UI thread is executing lines while it's waiting
sibber
sibber2y ago
like task.then(...).then(...) isnt needed
Thalnos
Thalnos2y ago
the ppoint of await is to run code asnychronously but in a "synchronous fashion" which means in order but not blocking
sibber
sibber2y ago
wdym
Tim
TimOP2y 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
sibber2y ago
exactly
Tim
TimOP2y ago
So it's not entirely 'line by line' which feels odd if you don't know how it works but yeah
sibber
sibber2y ago
yeah, but in the context of the method it is
Tim
TimOP2y ago
yup
sibber
sibber2y ago
everything does :)
Tim
TimOP2y ago
ty for the help I gotta catch a bus ^-^ have a nice day!
sibber
sibber2y ago
np you too :)
Thalnos
Thalnos2y 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
TimOP2y ago
Will check out the links.
Thalnos
Thalnos2y 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
Accord2y 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.

Did you find this page helpful?