C# 当调用异步方法时会发生什么?

C# 当调用异步方法时会发生什么?,c#,.net,async-await,C#,.net,Async Await,我试图理解为什么使用“异步”方法比使用简单的旧同步方法更好 有一个小问题我不明白 在同步方式上: 我有一些线程调用方法FileStream.Read。。。。 因为调用此方法是同步的,所以调用线程将等待直到IRP I/O请求包发出此Io请求完成的信号。 直到IRP返回==>此线程将暂停睡眠。 在A同步方式上: 我有一些线程任务。。让我们调用此线程“TheadAsync01”,该线程调用方法FileStream.ReadAsync。。。。 因为调用此方法是A同步的,所以调用线程不会等到IRP I/O

我试图理解为什么使用“异步”方法比使用简单的旧同步方法更好

有一个小问题我不明白

在同步方式上:

我有一些线程调用方法FileStream.Read。。。。 因为调用此方法是同步的,所以调用线程将等待直到IRP I/O请求包发出此Io请求完成的信号。 直到IRP返回==>此线程将暂停睡眠。 在A同步方式上:

我有一些线程任务。。让我们调用此线程“TheadAsync01”,该线程调用方法FileStream.ReadAsync。。。。 因为调用此方法是A同步的,所以调用线程不会等到IRP I/O请求包发出该IO请求完成的信号;这个调用线程将继续执行他的下一个操作。 现在,IRP何时会发出此IO请求已完成的信号?发生了什么

线程TheadAsync01现在正在执行其他操作,无法继续处理“FileStream.ReadAsync”现在返回的内容

其他线程是否将继续执行下一个操作,返回值为ReadAsync


我不明白的是什么

它困扰你的原因是这个错误的假设:

线程TheadAsync01正在执行其他操作,无法继续 “FileStream.ReadAsync”现在返回的内容

在典型的应用程序中,I/O是迄今为止最耗时的任务

正确使用TPL时,线程不会被耗时的操作阻塞。相反,一切都很耗时——换句话说,任何I/O都是通过WAIT进行委派的。因此,当您的IRP发出信号时,线程将要么从工作中解脱出来,要么很快就会解脱出来


如果有一些繁重的计算,而不是I/O,那么您需要相应地计划,例如在专用线程上运行它。

它困扰您的原因是错误的假设:

线程TheadAsync01正在执行其他操作,无法继续 “FileStream.ReadAsync”现在返回的内容

在典型的应用程序中,I/O是迄今为止最耗时的任务

正确使用TPL时,线程不会被耗时的操作阻塞。相反,一切都很耗时——换句话说,任何I/O都是通过WAIT进行委派的。因此,当您的IRP发出信号时,线程将要么从工作中解脱出来,要么很快就会解脱出来


如果有一些繁重的计算,而不是I/O,那么您需要相应地计划,例如在专用线程上运行它。

当***异步方法返回一个或多个任务时,您可以使用它来跟踪异步操作的运行。您可以通过调用使调用与调用代码同步。等待任务。或者,从.NET4.5开始,您可以等待该任务

e、 g:


在这种情况下,任何后续代码都将由编译器包装在一个延续中,并在异步调用完成时执行。使用async关键字的一个要求是使用async关键字标记调用方法,请参见上面的示例。

当***async方法返回一个或多个任务时,您可以使用它来跟踪异步操作的运行。您可以通过调用使调用与调用代码同步。等待任务。或者,从.NET4.5开始,您可以等待该任务

e、 g:


在这种情况下,任何后续代码都将由编译器包装在一个延续中,并在异步调用完成时执行。使用async关键字的一个要求是使用async关键字标记调用方法,请参见上面的示例。

函数ReadAsync立即返回一个值,即任务对象。在某个地方,您应该使用返回值做一些事情。标准方法是使用wait:

await FileStream.ReadAsync(...)
这将确保调用站点在ReadAsync完成其作业之前不会继续操作。如果您想同时执行某些操作,可以稍后等待任务对象,也可以手动处理任务对象


如果您只是调用ReadAsync,忽略返回的任务对象,对其不做任何处理,那么您的读取通常是一个昂贵的禁止操作。

函数ReadAsync立即返回一个值,即任务对象。在某个地方,您应该使用返回值做一些事情。标准方法是使用wait:

await FileStream.ReadAsync(...)
这将确保调用站点在ReadAsync完成其作业之前不会继续操作。如果您想同时执行某些操作,可以稍后等待任务对象,也可以手动处理任务对象

如果您只是调用ReadAsync,忽略返回的任务对象,对其不做任何处理,那么您的读取通常是一个昂贵的禁止操作。

如果它不会继续执行下一条指令,那么它将或多或少地注册一个回调,其结果将继续
使用下一条指令并释放线程。当IO完成时,它将调用一个新线程上的回调并从那里继续读取。如果它不继续执行下一条指令,它将或多或少地注册一个回调,其结果将继续执行下一条指令并释放线程。当IO完成时,它将调用一个新线程上的回调并从那里继续。当然,你可以在一个线程上做耗时的工作。例如,当执行并行工作时-TPL中的P-在等待IO时阻塞一个完整的线程是很遗憾的-在这种情况下,将是零work@CarstenK差不多,我想调度员在某些任务中使用IO完成端口。当然,您可以在线程上执行耗时的工作,例如在执行并行工作时-TPL中的P-在等待IO时阻塞完整的线程是很遗憾的-在这种情况下,将为零work@CarstenKönig我认为调度程序在某些任务中使用IO完成端口。因此,返回的“任务”是否为新任务?这会导致创建一个新线程吗?是的。它是由底层ReadAsync调用创建的。那么,返回的“Task”是新任务吗?这会导致创建一个新线程吗?是的。它是由底层ReadAsync调用创建的