c# - 异步等待性能 - 直接方法调用与任务包装器调用

标签 c# .net asynchronous task-parallel-library task

我创建的一个小程序,用于理解 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/

相关文章:

c# - 在 Windows 窗体应用程序中访问以自定义文件类型保存的数据

c# - 如何读取 ""之间的文本文件

c# - Transient 注入(inject) Singleton 有什么问题?

node.js - [tokio-rs] [文档]具有共享状态示例的多个异步 “sub-apps”?

python - aiohttp 下载大量 pdf 文件列表

c# - 单声道 Gtk# : ButtonPressEvent not work

c# - 如何让 WinForms 图表控制主 Y 轴绘制在图表的两边?

Java BigInteger 与 Mono .net BigInteger

c# - 如何在谷歌标记 map 上使用 C# .net MVC 框架显示 Azure Cosmos DB 数据?

java - 如何在多线程环境中异步登录?