mbu*_*nik 22 .net c# asynchronous async-await
我很好奇异步等待线程内部.
每个人都声明async在性能方面要好得多,因为它释放了等待长异步调用响应的线程.好的我明白了.
但让我们考虑一下这种情况.
我有一个异步方法在数据库上执行异步操作.数据库的api公开函数BeginQuery和事件QueryCompleted.我用任务包装了那些(使用TaskCompletionSource).
我的问题是调用BeginQuery和触发事件QueryCompleted之间的内幕.
我的意思是 - 它不需要产生某种工人来解雇事件吗?在非常低的级别,它必须是一些阻止来自db的线程读取结果的同步循环.
我认为任何异步调用都必须生成一个线程来实际处理响应(可能在驱动程序代码中的低级c ++循环中等待它).
所以我们唯一的"收获"是当一些其他线程正在执行其工作时,可以释放调用者线程.
调用异步方法总是创建一个新的工作线程吗?
有人可以证实我的理解吗?
我的意思是 - 它不需要产生某种工人来解雇事件吗?在非常低的级别,它必须是一些阻止来自db的线程读取结果的同步循环.
它将创建一个IO完成端口(IOCP),表示正在外部处理的任务,该线程将继续执行其他操作.然后,当IOCP通知任务完成时,线程将获取IOCP的状态并继续执行任务.
http://www.drdobbs.com/cpp/multithreaded-asynchronous-io-io-comple/201202921
I/O完成端口为编写使用多线程和异步I/O的可伸缩服务器应用程序的问题提供了一个优雅的解决方案.
我的意思是 - 不需要产生某种工人来触发事件吗?在非常低的级别,它必须是某个同步循环阻塞了从 db 读取结果的线程。
即使您实际上必须等待内核对象(例如手动重置事件),您仍然可以将阻塞的同步代码转换为异步代码并将线程从阻塞中释放出来(更新:真实场景)。
例如,同步代码:
void Consume()
{
var completedMre = new ManualResetEvent(false);
producer.StartOperation(completedMre);
completedMre.WaitOne(); // blocking wait
Console.WriteLine(producer.DequeueResult());
}
Run Code Online (Sandbox Code Playgroud)
异步模拟:
async Task ConsumeAsync()
{
var completedMre = new ManualResetEvent(false);
producer.StartOperation(completedMre);
var tcs = new TaskCompletionSource<Result>();
ThreadPool.RegisterWaitForSingleObject(completedMre,
(s, t) => tcs.SetResult(producer.DequeueResult()),
null, Timeout.Infinite, true);
var result = await tcs.Task;
Console.WriteLine(result);
}
Run Code Online (Sandbox Code Playgroud)
异步版本最多可扩展 64 倍(MAXIMUM_WAIT_OBJECTS
,这是可以聚合RegisterWaitForSingleObject
以等待单个线程的内核对象的最大数量)。因此,您可以Consume()
并行调用64 次,它将阻塞 64 个线程。或者你可以调用ConsumeAsync
64 次,它只会阻塞一个线程。
归档时间: |
|
查看次数: |
4387 次 |
最近记录: |