What is so special about a user interface thread?

Let's say I have a fooCPU method that works synchronously (it does not call pure asynchronous methods that execute I / O, or uses other threads to run its code by calling Task.Run or similar methods). This method does some heavy computing - it is CPU related.

Now I call fooCPU in my program without delegating its execution by the workflow. If one line from fooCPU takes a long time, no other lines will be executed until it ends. So, for example, calling it from the user interface thread causes the user interface thread to freeze (the GUI stops responding).

When I said that async/await is a mutlithreading imitation. Lines of two different code fragments are executed in turn in one thread. If one of these lines takes a long time, no other lines will be executed until it completes.,

I was told that this is true for async used in the user interface thread, but this is not the case for all other cases (ASP.NET, async in the thread pool, console applications, etc.).

Can someone tell me what this can mean? How is the user interface different from the main console program stream?

I think no one wants anyone here in this forum to continue the discussion on how they appear in the comments, for example, so it’s better to ask a new question.

+6
source share
3 answers

I recommend you read my async post post ; he explains how the async and await keywords work. Then, if you are interested in writing asynchronous code, go to my async article.

Relevant parts of the opening post:

The start of the asynchronous method is done exactly like any other method. That is, it works synchronously until it reaches “wait” (or throws an exception).

This is why the internal method in your console code example (without await ) was executed synchronously.

Waiting verifies that it expects that it is already completed; if the expected is already completed, the method simply continues to work (synchronously, like a regular method).

This is why the external method in your console code example (which was await internal method that was synchronous) was executed synchronously.

Later, when the wait is complete, it will execute the remainder of the asynchronous method. If you expect a built-in wait (for example, a task), then the remainder of the async method will execute in a "context" that was captured before the "wait" returns.

This "context" is SynchronizationContext.Current , if it is not null , in which case it is TaskScheduler.Current . Or a simpler version:

What is this "context"? Simple answer:

  • If you are using a UI thread, then this is the UI context.
  • If you are responding to an ASP.NET request, then this is the ASP.NET request context.
  • Otherwise, this is usually the context of the thread pool.

Putting it all together, you can visualize async / await as follows: a method is split into several “pieces”, with each await acting as the point where the method is split. The first block always starts synchronously, and at each split point it can continue either synchronously or asynchronously. If it continues asynchronously, it will continue in the captured context (by default). UI threads provide the context that the next fragment in the UI thread will execute.

So, to answer this question, a special topic about user interface threads is that they provide a SynchronizationContext , that queues return to the same user interface thread.

I think no one wants anyone here in this forum to continue the discussion on how they appear in the comments, for example, so it’s better to ask a new question.

Well, Qaru is not intended for forums; this is a question and answer site. So this is not the place to ask for comprehensive study guides; this is the place where you are stuck trying to get the code to work, or if you don’t understand anything, having studied everything you can. This is why comments on SO (purposefully) are limited - they should be short, beautiful code formatting, etc. The comments on this site are for clarification, and not as a discussion or forum.

+10
source

It's pretty simple, a thread can only do one thing at a time. Therefore, if you send a UI thread in the forest that does something not related to the UI, say a dbase request, then all UI activity stops. No more screen updates, no response to mouse clicks and keystrokes. He looks and acts frozen.

You will probably say, "well, I'm just using a different thread to create the user interface." It works in console mode, sort of. But not in a GUI application, making the code safe is thread safe, and the user interface is not thread safe at all, because so much code is involved. Not the kind you wrote, the kind you use with the cover of a library of fancy classes.

A universal solution is to invert this, to do non-UI things in the workflow, and leave the user interface stream only to take care of the lightweight user interface material. Async / await helps you do this, which is rightfully expected to work for an employee. The only way to mess this up, and it's not uncommon, is to ask the UI thread to still do too much work. Like adding a line of text to a text box once every millisecond. It’s just a bad UI design, people don’t read it fast.

+9
source

Considering

 async void Foo() { Bar(); await Task.Yield(); Baz(); } 

You are right that if Foo() receives a call in the user interface thread, then Bar() is called immediately, and Baz() is called later, but still in the user interface thread.

However, this is not a property of the threads themselves.

What actually happens is that this method is split into something similar to

 Task Foo() { Bar(); return Task.Yield().Continue(() => { Baz(); }); } 

This is not entirely correct, but the ways in which it is wrong do not matter.

The argument that passes to my hypothetical Continue method is code that can be defined in some way defined by the task. A task may decide to execute it immediately, it may decide to execute it at some later point in the same thread, or it may decide to execute it at some later point in another thread.

Actually, the tasks themselves do not solve, they simply pass the SynchronizationContext delegate. This synchronization context determines what to do with executable code.

And what is different between the types of threads: as soon as you access any WinForms control from a thread, then WinForms sets the synchronization context for that particular thread, which will schedule the code to be executed at some later point on the same thread.

ASP.NET, background threads, all different synchronization contexts and what causes changes in how the code runs.

+3
source

All Articles