我创建的一个小程序,用于理解 Async Await 的工作原理并在 for 循环中调用异步方法,作为直接方法调用:
sumProgram.CallSum(i, i + 1);
或使用任务 API Task.Run/Task.Factory.StartNew
我最初的理解是 Task API 会大大加快它的速度,但与我的预期相反,这肯定反射(reflect)了我的理解不足,直接调用在性能方面要好得多。事实上,当在 GetSum 方法中引入额外的线程 sleep 时,它似乎只影响任务调用,而且影响也很大。
现在我明白直接调用的第一部分更快,因为它们是异步执行的,并且没有添加到任务列表并让它们等待的开销,但是当我将相同的技术转移到真正的编程范例时,那么问题依然存在:
对于直接调用,没有什么可以模拟 Task.WaitAll,所以他们会退出调用方法,即使所有的执行都没有完成,所以这是我唯一的选择 Task wrapper。
我是否得到了令人费解的结果,因为对于直接调用,秒表甚至会在所有执行完成之前发布时间,而由于 waitAll,任务包装器不会出现这种情况
为了执行这个程序,您需要注释/取消注释相关部分以获得正确的结果
class Program { static void Main(string[] args) { Program sumProgram = new Program(); List<Task> taskList = new List<Task>(); // Only For Task Stopwatch sw = Stopwatch.StartNew(); for (int i = 0; i < 100000; i++) { taskList.Add(Task.Factory.StartNew(() => { sumProgram.CallSum(i, i + 1); })); // For Task use one taskList.Add(Task.Run(() => { sumProgram.CallSum(i, i + 1); })); // For Task use one sumProgram.CallSum(i, i + 1); } Task.WaitAll(taskList.ToArray()); // Only For Task sw.Stop(); Console.WriteLine("Time Elapsed :: " + sw.ElapsedMilliseconds); } public async Task CallSum(int num1, int num2) { Func<int> callFunc = (() => { return GetSum(num1, num2); }); int result = await Task.Run<int>(callFunc); //Console.WriteLine("Sum Result :: " + result); } public int GetSum(int num1, int num2) { Thread.Sleep(10); return (num1 + num2); } }
最佳答案
异步
!= "更快"
事实上,async
代码几乎总是(稍微)慢一些。
那么,为什么要使用async
?
在客户端 (UI) 应用程序中,async
允许您保持对用户的响应。对比这段代码:
void Button_Click()
{
Thread.Sleep(10000);
}
使用此代码:
async void Button_Click()
{
await Task.Delay(10000);
}
在服务器端(例如 ASP.NET),async
允许您的代码使用更少的线程来服务更多的请求。因此,增加了可扩展性。
请注意,在这两种情况下,异步
代码实际上比同步代码慢。对于 UI,让当前线程休眠比创建并启动计时器、创建并等待任务,然后在计时器触发时恢复异步方法更快。对于 ASP.NET,阻塞当前线程比为异步操作创建任务,然后在异步方法恢复时将请求上下文切换到另一个线程要快。
但是,async
带来了其他好处。对于UI,UI线程在延迟期间不会被阻塞。对于 ASP.NET,请求线程可以在异步操作进行时自由地处理其他请求。
async
与速度无关;它是关于释放当前线程。
关于c# - 异步等待性能 - 直接方法调用与任务包装器调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26192100/