简体   繁体   English

有关在C#异步等待期间在主线程上运行什么的问题

[英]Questions about what runs on the main thread during c#'s async await

I'm having trouble understanding what runs on the main thread during an async await operation and would be grateful for some answers. 我在理解异步等待操作期间在主线程上运行的内容时遇到了麻烦,将不胜感激。

Let's say I have a button that is supposed to log the user in. 假设我有一个应该用于登录用户的按钮。

it is supposed to block all other user input while the login process transpires, show a progress view and then when the result comes in display it 它应该在登录过程发生时阻止所有其他用户输入,显示进度视图,然后在显示结果时显示它

and here is the method that performs the log in 这是执行登录的方法

button_clicked(object sender, EventArgs e) {
    do_login(); //I do not await the result
    do_some_other_stuff(); //this doesn't actually exist I just put it here to ask my questions
}

async Task do_login() {
    string user_name = txtUser.Text;
    string password = txtPassword.Text;
    show_progress(true); //this is not an async method;
    string error = await _login.do_login(user_name, password);//this is an async method that can take up to 20 seconds to complete;
    show_progress(false);
    if (error != null) {
        show_error(error);
    } else {
        show_next_screen();
    }
}

I have two questions on the above example 关于以上示例,我有两个问题

a) What will be run on the main thread? a)将在主线程上运行什么?

If I understand it correctly only _login.do_login will be run on a seperate thread, all others will be on the main thread, is this correct? 如果我正确理解它,则仅_login.do_login将在单独的线程上运行,其他所有线程都将在主线程上运行,这是否正确?

b) In what order will the methods be executed? b)这些方法将以什么顺序执行?

Again if I understand it correctly, it will be : 再次,如果我理解正确,它将是:

  • do_login() do_login()
  • show_progress(true); show_progress(true);
  • _login.do_login starts; _login.do_login开始;
  • do_some_other_stuff(); do_some_other_stuff();
  • _login.do_login finishes; _login.do_login完成;
  • show_progress(false); show_progress(false); and it will continue from there 它会从那里继续

is this correct? 这个对吗? if not, how can I achieve such a behaviour? 如果没有,我如何实现这种行为?

c) If my code above is correct then why do I keep receiving a warning that do_login() is not awaited? c)如果我上面的代码是正确的,那么为什么我继续收到未等待do_login()的警告? I do not wish to await it I just want it to run what it can and return when it wants, should I ignore that warning? 我不想等待它,我只是希望它运行它可以运行的并在需要时返回,我是否应该忽略该警告?

Technically, depending on the implementation of do_login , everything could run in the main thread. 从技术上讲,取决于do_login的实现,所有内容都可以在主线程中运行。 In this case I assume you're contacting a web server, so that part won't, but this is not always true. 在这种情况下,我假设您正在与Web服务器联系,因此不会进行此操作,但这并非总是如此。 And asynchronous operation does not necessarily executes in another thread. 并且异步操作不一定在另一个线程中执行。 One operation is asynchronous when: 在以下情况下,一种操作是异步的:

  • It doesn't block the calling thread. 它不会阻塞调用线程。

Usually, UI threads run an 'event loop'. 通常,UI线程运行“事件循环”。 So an asynchronous task could simply put a new piece of work into the event queue to be executed whenever the scheduler determines, but in the same thread. 因此,异步任务可以简单地将新的工作放入事件队列中,以便在调度程序确定时在同一线程中执行。 In this case you don't use two threads, but still, you don't have to wait for the task to complete and you don't know when it'll finish. 在这种情况下,您无需使用两个线程,但是,您不必等待任务完成,也不知道何时完成任务。

To be precise, all the code in your post will run in the main thread. 确切地说,您帖子中的所有代码都将在主线程中运行。 Only the part in do_login that manages the connection with the server, waiting and retrieving data will execute asynchronously. do_login中仅管理与服务器的连接,等待和检索数据的部分将异步执行。

You're mostly right about the sequence, with a few adjustments: 您对序列最正确,但需要进行一些调整:

  1. do_login() (until the await) do_login()(直到等待)
  2. login._do_login() starts executing login._do_login()开始执行
  3. do_some_other_stuff() do_some_other_stuff()
  4. ... ...
  5. login.do_login finishes login.do_login完成
  6. show_progress() show_progress()

The answer to your main question is: it depends . 您的主要问题的答案是: 取决于 The _login.do_login method will likely be put onto its own thread, but it actually depends on the .NET task scheduler. _login.do_login方法可能会放在其自己的线程上,但实际上取决于.NET任务计划程序。 In WPF and ASP.NET it will be scheduled onto the thread pool if it doesn't immediately return a completed task. 在WPF和ASP.NET中,如果它不立即返回完成的任务,则将其安排在线程池中。

The important part is that you know it will not block execution of the calling (in your case, the main) thread. 重要的部分是您知道它不会阻止调用线程(在您的情况下为主线程)的执行。 Your understanding of the method flow is correct since you don't await do_login . 您对方法流程的理解是正确的,因为您无需等待do_login

As far as the warning goes; 就警告而言; you can mark do_login as async void to avoid it, though generally you only do that for event handlers which can then await a Task returning method. 您可以将do_login标记为async void以避免它,尽管通常只对事件处理程序执行此操作,然后该事件处理程序可以等待Task返回方法。 If you do go the async void route; 如果您确实走了async void路线; make sure to put a try/catch in as such methods will throw all the way up to the root handler and can cause your app to crash. 请确保try/catch ,因为此类方法将一路抛出到根处理程序,并可能导致您的应用崩溃。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM