【问题标题】:how to calculate execution time of a async method in c#如何在c#中计算异步方法的执行时间
【发布时间】:2018-11-03 05:42:06
【问题描述】:

所以我有一个异步执行某些操作的 Async 方法。

private async static void DoSomethingAsync (int i){}

我循环调用它,比如说 50 次。

for (int i = 0; i < 50; i++)
 {
    DoSomethingAsync (i);
 }

在循环结束时,我想计算总处理时间,我使用了 Stopwatch,但你可以想象它给了我错误的时间,因为它在循环结束后立即被调用,它不会等待 DoSomethingAsync 完成处理.

如何告诉 Stopwatch 等待所有 50 个 DoSomethingAsync() 实例完成。我看过this的问题,但我不能在这里使用Task。

【问题讨论】:

  • 为什么不能使用Task?
  • 你只开始了50个任务,你不知道它们什么时候完成。避免使用async void,除非您确切了解为什么[不] 使用它们。

标签: c# .net asynchronous async-await stopwatch


【解决方案1】:

我不知道您为什么不能使用 Task,我猜您是在 Main 方法或其他方法中调用它。所以我会离开那个。

就像 Martin Ullrich 说的我会改变 DoSomethingAsync 方法来返回一个任务:

private async static Task DoSomethingAsync(int i)
{
    ...
}

然后通过将方法添加到List&lt;Task&gt; 来创建一个执行循环的新方法:

private static async void PerformLoop()
{
    Stopwatch timer = new Stopwatch();
    timer.Start();
    List<Task> l = new List<Task>();
    for (int i = 0; i < 50; i++)
    {
        l.Add(DoSomethingAsync(i));
    }
    await Task.WhenAll(l);
    timer.Stop();

    Console.WriteLine(timer.Elapsed.TotalSeconds);
}

现在从您之前执行循环的位置开始,在这种情况下,Main 方法只需在其中添加新方法调用:

static void Main(string[] args)
{
    PerformLoop();

    Console.ReadLine();
}

【讨论】:

    【解决方案2】:

    这是使用async void 的缺点。如果不修改被调用的方法(以便它可以调用回调、解锁互斥锁等),就无法做到这一点。

    您可以更改您的方法以返回 async Task,并创建另一个方法,该方法只调用此方法而无需等待,然后可以在您以前需要 async void 签名的地方使用该方法。

    【讨论】:

      【解决方案3】:

      async void 为什么?不要那样做,使用asnyc Task,或ActionBlocks 或ParallelFor/ForEach。然而纯粹是为了新颖(而不是用作真正的衡量标准),如果您想计算并行进程 id 中的时间,请考虑在并行方法中放置一个计时器并使用全局变量并使用 Interlocked.Add Method 线程安全方法

      private long CombinedMs;
      
      ...
      
      private async static void DoSomethingAsync (int i)
      {
      
         var sw = new StopWatch();
         sw.Start();
         ...
         sw.Stop();
      
         Interlocked.Add(ref CombinedMs,sw.ElapsedMillisecond);
      
      }
      

      无论如何,我认为你需要回到绘图板上完成任务......祝你好运

      【讨论】:

        【解决方案4】:

        你可以有一个全局计数器来跟踪消耗的时间,就像这样。

        public class YourClass
        {
        
        TimeSpan tSpan;
        
        
        public void PerformOp()
        {
        tSpan=new TimeSpan();
        for (int i = 0; i < 50; i++)
         {
            DoSomethingAsync (i);
         }
        
        }
        
        private async static void DoSomethingAsync (int i)
        {
        Stopwatch stp = new StopWatch();
        stp.Start();
        //your Operation here
        stp.Stop();
        tSpan+=stp.Elapsed;//not the exact systax or usage but you get the idea 
        }
        
        }
        

        【讨论】:

          猜你喜欢
          • 2021-08-10
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-12-10
          • 2017-06-21
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多