理解C#中的“async/await”模式(Java开发人员)

3
我来自Java开发环境,开始学习C#编程。我注意到C#中有一个我从未在Java中见过的“async/await”模式。它到底是什么?我浏览了一段时间的互联网,但找不到明确的解释来澄清我的理解。
所以让我们定义以下场景: 1. 线程'T'(例如GUI线程)正在执行GUI异步函数'F' 2. 在该异步函数'F'的某个点上,我们在“可等待”的对象'A'(最可能是Task / Task<>)上调用'await'。 3. 然后,“await”调用将释放/暂停执行线程'T'(在本例中为GUI线程),以便在“可等待”'A'执行其工作时运行/执行其他任务。 4. 当“可等待”'A'对象完成其工作时,异步函数'F'的执行会恢复。
在上述场景中(如果我描述得正确),哪个线程将执行“awaitable”'A'方法? 是GUI线程还是来自池中的其他线程?如果是池线程(而不是GUI线程)并且我正在访问GUI资源(例如按钮,标签,网格视图等),那么我会破坏GUI线程数据吗?请记住,我来自Java世界,那里只有一个GUI线程可以更改/操作GUI资源。

看看Stephen Cleary的博客。对于更加学术化的观点,Eric Lippert也在他的博客上谈到了它(他从continuations的角度开始)。 - Flydog57
看看这个:async/await. Where is continuation of awaitable part of method performed?。简短的回答是:这取决于项目的类型,以及您是否使用了ConfigureAwait(false) - Theodor Zoulias
C#也有一个UI线程,因此相同的概念适用。如果您需要从非UI线程与UI交互,请使用BackgroundWorker:https://dev59.com/questions/u3I_5IYBdhLWcg3wJfgM#1507337 - Mike Lowery
3个回答

1
首先,这两种语法是不同的。
线程语法:
Thread thread = new Thread(() => VoidMethod("","",""));

thread.Start();

https://www.c-sharpcorner.com/blogs/asynchronous-multithreaded-programming-with-example-in-c-sharp

如果您使用此线程没有返回任何值,则整个请求完成。

任务/任务<>语法 :-

public async Task<int> VoidMethod("","","")
{
   await Task.Run(() => VoidMethod("","",""));
   return 1; 
}

https://www.c-sharpcorner.com/article/async-and-await-in-c-sharp/

如果您使用这种方法,将会返回值。在整个请求完成时返回。

如果您的请求需要时间,请等待完成后再发出另一个请求。如果用户连续发送请求,直到第一个请求完成后再次发送请求。使用task/await方法是不正确的。 - chandu komati
如果请求需要花费时间并且用户希望连续请求访问数据,则线程是最佳选择。 - chandu komati
我想我理解了,但我的问题是,在我上面描述的情况下,哪个线程用于执行可等待方法? - Rejkid

0

-1
  • await() 可能会导致异步方法返回,但其执行并未完成,它将在稍后的某个时间再次被调用。为了在稍后被调用,它在返回之前进入到某个事件的队列中,就像线程可以在 Java 中调用 Object.wait() 一样,这意味着线程进入到某个事件的队列中并离开处理器。异步方法离开线程,因为线程对它起着处理器的作用。

  • 当事件发生时,异步方法恢复执行,也就是说,它会在下一个可用的线程池线程上再次被调用,就像在等待(wait())之后的线程在下一个可用的处理器上运行一样。为了不从头开始继续执行,而是从上次因为 await() 而返回的地方继续执行,状态信息被保存,然后以以下形式使用: switch(state) { case 0: goto 0'; case 1: goto 10'; .... }

  • 请注意,这是字节码,因此可以使用 goto。为了保存状态,我们需要一个对象的字段,因此异步方法实际上不是一个方法,而是一个类,在第一次调用它的地方实例化。

    由于直接使用goto,在普通的C#或Java中编写异步方法很难或有时不可能。但是,将异步方法的每个部分编写为单独的方法并将这些方法用作等待事件的回调始终是可能的。Async/await只是另一种异步编程语法,与回调、actors、ComplatableFuture、java.util.concurrent.Flow等一样。


    当你说“当事件发生时,异步方法被恢复,也就是说,它会在线程池的下一个可用线程上再次调用” - 这是正确的吗?我认为它必须继续在同一GUI线程“T”上运行,而不是在任何池线程上(C#是否像Java一样只有一个GUI线程?) - Rejkid
    当异步方法在异步等待之后恢复时,它将尝试在同一“上下文”中恢复。如果它是在GUI线程上启动的,它将尝试在那里继续。如果它是在GUI线程外启动的,它将永远不会在GUI线程上继续。请参见https://social.msdn.microsoft.com/Forums/en-US/269172a3-adb9-4b5e-9ac1-8b67ff920177/async-issuewhy-blocking-the-ui-thread?forum=async - Alexei Kaigorodov
    “it will attempt to continue there”是什么意思 - 它能在不同于GUI线程的线程上运行吗?C#中的GUI线程不像Java一样只有一个线程吗? - Rejkid

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接