【问题标题】:Using the Stopwatch with Async methods使用带有异步方法的秒表
【发布时间】:2013-10-15 12:37:08
【问题描述】:

我有一些代码如下:

public void Start()
{
    var watch = new Stopwatch();
    watch.Start();

    Task.Factory.StartNew(MyMethod1);
    Task.Factory.StartNew(MyMethod2);

    watch.Stop();
    Log(watch.ElapsedMilliseconds);
    Task.Factory.StartNew(MyMethod3);
}

因为 MyMethod1 和 MyMethod2 被异步调用 watch.Stop() 在错误的时间被调用。如何确保在 MyMethod1 和 MyMethod2 完成后调用和记录 .Stop 但确保 MyMethod3 不必等待。

我想在我的 Start() 方法中保留所有 Stopwatch 功能,而不是在我的 3 个方法中的任何一个中记录日志,即 MyMethod1、MyMethod2 和 MyMethod3

【问题讨论】:

    标签: c# .net multithreading .net-4.0 task-parallel-library


    【解决方案1】:

    您可以使用Task.Factory.ContinueWhenAll 方法。

    watch.Start();
    var t1 = Task.Factory.StartNew(MyMethod1);
    var t2 = Task.Factory.StartNew(MyMethod2);
    Task.Factory.ContinueWhenAll(new [] {t1, t2}, tasks => watch.Stop());
    

    如果您的目标是 .NET 4.5 及更高版本,您还可以使用方法Task.WhenAll。它返回一个任务,该任务将在所有传递的 Task 对象完成后完成。

    Task.WhenAll(t1, t2).ContinueWith(t => watch.Stop());
    

    【讨论】:

      【解决方案2】:

      您需要创建一个新线程来处理日志记录问题。 此日志记录线程将在包含所有线程 EventWaitHandles 的 EventWaitHandle.WaitAll(threadsEventWaitHandles) 上等待。 类似的东西:

      private void LoggingThread()
      {
          var watch = new Stopwatch();
          watch.Start();
      
          EventWaitHandle.WaitAll(threadsEventWaitHandles);
      
          watch.Stop();
          Log(watch.ElapsedMilliseconds);
      }
      

      而且MyMethod1, MyMethod2 方法在完成时也会向日志线程发出信号。 类似的东西:

      private void MyMethod1()
      {
          //... your code
          EventWaitHandle.Set();
      }
      
      private void MyMethod2()
      {
          //... your code
          EventWaitHandle.Set();
      }
      

      因此您可以确保 MyMethod3 不必等待。

      【讨论】:

      • ContinueWhenAll() 更简单也更高效。
      • @svick,你说得对,我不知道这种技术。谢谢。
      【解决方案3】:
          public void Start()
          {
              var watch = new Stopwatch();
              watch.Start();
      
              Task.Factory.StartNew(MyMethod1);
              Task.Factory.StartNew(MyMethod2);
      
              Task.WaitAll(); // Wait for previous tasks to finish
      
              watch.Stop();
              Log(watch.ElapsedMilliseconds);
              Task.Factory.StartNew(MyMethod3);
          }
      

      【讨论】:

      • "...但要确保 MyMethod3 不必等待。"
      • +1,一个非常简单的解决方案。我的思路是ContinueWith
      猜你喜欢
      • 1970-01-01
      • 2019-03-27
      • 2019-06-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-12-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多