.net 4.5 中异步和同步的区别
difference between Asynchronous and Synchronous in .net 4.5
在我阅读 .Net 4.5 中的异步编程时 async
和 await
关键字
我阅读了Here下面的段落
Processing Asynchronous Requests
In web applications that sees a large number of concurrent requests at
start-up or has a bursty load (where concurrency increases suddenly),
making these web service calls asynchronous will increase the
responsiveness of your application. An asynchronous request takes
the same amount of time to process as a synchronous request. For
example, if a request makes a web service call that requires two
seconds to complete, the request takes two seconds whether it is
performed synchronously or asynchronously. However, during an
asynchronous call, a thread is not blocked from responding to other
requests while it waits for the first request to complete. Therefore,
asynchronous requests prevent request queuing and thread pool growth
when there are many concurrent requests that invoke long-running
operations.
对于粗体字,我无法理解为什么异步请求与同步请求需要相同的时间来处理?
例如:
public async Task MyMethod()
{
Task<int> longRunningTask = LongRunningOperation();
//indeed you can do independent to the int result work here
//and now we call await on the task
int result = await longRunningTask;
//use the result
Console.WriteLine(result);
}
public async Task<int> LongRunningOperation() // assume we return an int from this long running operation
{
await Task.Delay(1000); //1 seconds delay
return 1;
}
我的理解是 LongRunningOperation()
从第一行开始执行,这里调用 Task<int> longRunningTask = LongRunningOperation();
和 returns 调用 await
后的值,
所以从我的角度来看,异步代码比同步代码快,对吗?
另一个问题:
据我了解,正在执行 MyMethod()
的主线程并未阻塞等待 LongRunningOperation()
完成,但它 returns 进入线程池以服务于另一个请求。那么是否有另一个线程分配给 LongRunningOperation();
来执行它?
如果是那么异步编程和多线程编程有什么区别?
更新:
假设代码变成这样:
public async Task MyMethod()
{
Task<int> longRunningTask = LongRunningOperation();
//indeed you can do independent to the int result work here
DoIndependentWork();
//and now we call await on the task
int result = await longRunningTask;
//use the result
Console.WriteLine(result);
}
public async Task<int> LongRunningOperation() // assume we return an int from this long running operation
{
DoSomeWorkNeedsExecution();
await Task.Delay(1000); //1 seconds delay
return 1;
}
在这种情况下,LongRunningOperation()
是否会在DoIndependentWork()
执行期间被另一个线程执行?
异步操作并不快。如果您异步(即 await Task.Delay(10000)
)或同步(即 Thread.Sleep(10000)
)等待 10 秒,将花费相同的 10 秒。唯一的区别是 第一个在等待时不会占用线程,而第二个会 .
现在,如果您启动一个任务并且不等待它立即完成,您可以使用同一个线程来做一些其他工作,但它不会 "speed up" 异步操作的 运行:
var task = Task.Delay(10000);
// processing
await task; // will complete only after 10 seconds
关于您的第二个问题:Task.Delay
(与其他真正的异步操作一样)不需要执行线程,因此 there is no thread。 Task.Delay
是使用您启动的 System.Threading.Timer
实现的,它会在完成时引发一个事件,同时它不需要线程,因为没有要执行的代码。
因此,当 运行ning MyMethod
的线程到达 await longRunningTask
时,它会被释放(只要 longRunningTask
尚未完成)。如果它是一个 ThreadPool
线程,它将 return 到 ThreadPool
,它可以在您的应用程序中处理一些其他代码。
关于更新流程是这样的:
MyMethod
开始处理
LongRunningOperation
开始处理
DoSomeWorkNeedsExecution
在调用线程上执行
- 在
LongRunningOperation
中达到了 await
,因此 return 编辑了一个热门任务。
DoIndependentWork
由同一个调用线程执行(LongRunningOperation
仍然是"running",不需要线程)
- 在
MyMethod
中达到 await
。如果原始任务完成,同一个线程将同步继续,否则,将 return 编辑一个热任务,最终完成。
因此,您使用 async-await
的事实允许您使用一个线程,否则该线程将被阻塞以同步等待执行 CPU 密集型工作。
考虑两者的区别:
Thread.Sleep(1000);
和
await Task.Delay(1000);
两者都需要一秒钟才能到达 运行。然而,在前一种情况下,当前线程将被阻塞(并且其所有资源都无用),而在后一种情况下,当前线程可以做其他有用的事情(例如,服务于另一个请求)。
异步性不是关于加速单个指令序列,而是能够在同步代码阻塞时执行操作。
回复。 另一个问题
释放的线程将用于其他事情;在操作完成之前不会分配线程。这是可能的,因为底层 OS 本身是异步的。在上面的示例中,使用了一个计时器,它会在线程空闲时发出信号让线程启动,而不是线程因内部停止而停止。
(基于 I3arnon 的回答)
同步操作和使用 async-await
的操作总的来说花费相同的时间并不完全正确。
async-await
中涉及一些额外的逻辑。涉及已完成等待者和状态机的检查。这使得一些异步操作比相应的同步操作花费更多的时间。
另一方面,大多数适合 async-await
的操作自然是异步的,并且涉及一些额外的处理以使其看起来和感觉起来是同步的。在这些情况下,异步操作比同步操作花费的时间更少。
问题中的引述与网络应用程序有关。对于 Web 应用程序,异步操作更多的是在可接受的时间内为最大数量的请求提供服务,而不是为每个请求节省几微秒。另一方面,如果涉及上下文切换,最终会花费更多时间,这就是为什么在 Web 应用程序中使用 Task.Run
对应用程序弊大于利。
如果您想了解有关 async-awit
的更多信息,请阅读 my async-awit
curation 上的文章。
在我阅读 .Net 4.5 中的异步编程时 async
和 await
关键字
我阅读了Here下面的段落
Processing Asynchronous Requests
In web applications that sees a large number of concurrent requests at start-up or has a bursty load (where concurrency increases suddenly), making these web service calls asynchronous will increase the responsiveness of your application. An asynchronous request takes the same amount of time to process as a synchronous request. For example, if a request makes a web service call that requires two seconds to complete, the request takes two seconds whether it is performed synchronously or asynchronously. However, during an asynchronous call, a thread is not blocked from responding to other requests while it waits for the first request to complete. Therefore, asynchronous requests prevent request queuing and thread pool growth when there are many concurrent requests that invoke long-running operations.
对于粗体字,我无法理解为什么异步请求与同步请求需要相同的时间来处理?
例如:
public async Task MyMethod()
{
Task<int> longRunningTask = LongRunningOperation();
//indeed you can do independent to the int result work here
//and now we call await on the task
int result = await longRunningTask;
//use the result
Console.WriteLine(result);
}
public async Task<int> LongRunningOperation() // assume we return an int from this long running operation
{
await Task.Delay(1000); //1 seconds delay
return 1;
}
我的理解是 LongRunningOperation()
从第一行开始执行,这里调用 Task<int> longRunningTask = LongRunningOperation();
和 returns 调用 await
后的值,
所以从我的角度来看,异步代码比同步代码快,对吗?
另一个问题:
据我了解,正在执行 MyMethod()
的主线程并未阻塞等待 LongRunningOperation()
完成,但它 returns 进入线程池以服务于另一个请求。那么是否有另一个线程分配给 LongRunningOperation();
来执行它?
如果是那么异步编程和多线程编程有什么区别?
更新:
假设代码变成这样:
public async Task MyMethod()
{
Task<int> longRunningTask = LongRunningOperation();
//indeed you can do independent to the int result work here
DoIndependentWork();
//and now we call await on the task
int result = await longRunningTask;
//use the result
Console.WriteLine(result);
}
public async Task<int> LongRunningOperation() // assume we return an int from this long running operation
{
DoSomeWorkNeedsExecution();
await Task.Delay(1000); //1 seconds delay
return 1;
}
在这种情况下,LongRunningOperation()
是否会在DoIndependentWork()
执行期间被另一个线程执行?
异步操作并不快。如果您异步(即 await Task.Delay(10000)
)或同步(即 Thread.Sleep(10000)
)等待 10 秒,将花费相同的 10 秒。唯一的区别是 第一个在等待时不会占用线程,而第二个会 .
现在,如果您启动一个任务并且不等待它立即完成,您可以使用同一个线程来做一些其他工作,但它不会 "speed up" 异步操作的 运行:
var task = Task.Delay(10000);
// processing
await task; // will complete only after 10 seconds
关于您的第二个问题:Task.Delay
(与其他真正的异步操作一样)不需要执行线程,因此 there is no thread。 Task.Delay
是使用您启动的 System.Threading.Timer
实现的,它会在完成时引发一个事件,同时它不需要线程,因为没有要执行的代码。
因此,当 运行ning MyMethod
的线程到达 await longRunningTask
时,它会被释放(只要 longRunningTask
尚未完成)。如果它是一个 ThreadPool
线程,它将 return 到 ThreadPool
,它可以在您的应用程序中处理一些其他代码。
关于更新流程是这样的:
MyMethod
开始处理LongRunningOperation
开始处理DoSomeWorkNeedsExecution
在调用线程上执行- 在
LongRunningOperation
中达到了await
,因此 return 编辑了一个热门任务。 DoIndependentWork
由同一个调用线程执行(LongRunningOperation
仍然是"running",不需要线程)- 在
MyMethod
中达到await
。如果原始任务完成,同一个线程将同步继续,否则,将 return 编辑一个热任务,最终完成。
因此,您使用 async-await
的事实允许您使用一个线程,否则该线程将被阻塞以同步等待执行 CPU 密集型工作。
考虑两者的区别:
Thread.Sleep(1000);
和
await Task.Delay(1000);
两者都需要一秒钟才能到达 运行。然而,在前一种情况下,当前线程将被阻塞(并且其所有资源都无用),而在后一种情况下,当前线程可以做其他有用的事情(例如,服务于另一个请求)。
异步性不是关于加速单个指令序列,而是能够在同步代码阻塞时执行操作。
回复。 另一个问题
释放的线程将用于其他事情;在操作完成之前不会分配线程。这是可能的,因为底层 OS 本身是异步的。在上面的示例中,使用了一个计时器,它会在线程空闲时发出信号让线程启动,而不是线程因内部停止而停止。
(基于 I3arnon 的回答)
同步操作和使用 async-await
的操作总的来说花费相同的时间并不完全正确。
async-await
中涉及一些额外的逻辑。涉及已完成等待者和状态机的检查。这使得一些异步操作比相应的同步操作花费更多的时间。
另一方面,大多数适合 async-await
的操作自然是异步的,并且涉及一些额外的处理以使其看起来和感觉起来是同步的。在这些情况下,异步操作比同步操作花费的时间更少。
问题中的引述与网络应用程序有关。对于 Web 应用程序,异步操作更多的是在可接受的时间内为最大数量的请求提供服务,而不是为每个请求节省几微秒。另一方面,如果涉及上下文切换,最终会花费更多时间,这就是为什么在 Web 应用程序中使用 Task.Run
对应用程序弊大于利。
如果您想了解有关 async-awit
的更多信息,请阅读 my async-awit
curation 上的文章。