繁体   English   中英

WPF, 如何在同一时间同时执行多次异步方法?

[英]WPF , How to execute an async method many times simultaneously and in same time?

我正在编写一个WPF 项目模拟建筑物等不同结构中的视频显示。

在这个项目中,我使用了一种带有 bin 扩展名的特殊类型的二进制视频,其中 colors 被存储为红色、绿色和蓝色。

我有 2 种方法,第一种是“ReadDisplayBinFrames” ,它有 2 个任务,即读取 bin 视频并将其显示在结构上。 当然,由于这两个任务是异步的,所以我把方法定义为async

public async Task ReadDisplayBinFrames(Product product, bool PlayMode)
    {
        BinFile.SetPlayMode(PlayMode);

        int currentFrameNumber = 0;
        for (int i = 0; BinFile.IsPlayMode == true; i++)
        {
            for (currentFrameNumber = (int)product.LastFrameRead; currentFrameNumber <= product.BinFiles.TotalGame; currentFrameNumber++)
            {
                await Task.Run(() =>
                {
                    product.BinFiles.GetSphereColorFromBin(product.BinFiles.Read(currentFrameNumber), product.Wiring);
                    product.LastFrameRead = currentFrameNumber;
                    Debug.WriteLine($"LastFrameRead {product.LastFrameRead}");


                    product.Wiring.SetSphereColor(product.DelayPlay);
                });

                if (currentFrameNumber >= product.BinFiles.TotalGame)
                {
                    product.LastFrameRead = 0;
                }

                if (animPlayingMode == AnimPlayingMode.SerialAsync)
                {
                    BinFile.SetPlayMode(false);
                }
            }

        }
    }

因为我有一个结构列表并且我需要能够同时在每个结构上显示视频,所以我定义了一个名为“PlayBin”的方法。

private async void PlayBin()
    {
        InitBinList();

        for (int i = 0; i < Products.Count; i++)
        {
            if (animPlayingMode == AnimPlayingMode.ParallelSynchronous)
            {
                Parallel.Invoke(async () =>
                {
                    await ReadDisplayBinFrames(Products[i], true);
                    Debug.WriteLine($"LedProducts Count: {Products[i].LastFrameRead} of Product {i}");
                });
            }
            else
            {
                await ReadDisplayBinFrames(Products[i], true);
                Debug.WriteLine($"LedProducts Count: {Products[i].LastFrameRead} of Product {i}");
            }

        }
    }   

当我在一个结构上显示视频时,显示没有任何问题,但是当我增加结构的数量(例如,6)时,播放速度与只有一个结构的情况相比略有下降,并且在同时,失去了协调。 每个前进或后退几帧。

软件性能视频

Parallel.Invoke不支持异步方法。 它期望执行简单的 void 委托(例如Action<T> )。 这意味着,执行的委托将始终同步运行。

你的代码是一个很好的例子,为什么传递一个异步 lambda 作为一个Action的参数会引入一个潜在的错误:因为委托的调用者需要一个Action ,它不会await async方法。 async方法将返回Task ,调用者将立即继续(而不是等待此Task )。

在您的情况下, Parallel.Invoke将在async方法运行完成之前继续。 这将导致丢弃async上下文并导致意外行为。

另请注意, async方法必须始终返回TaskTask<T> (除非该方法是事件处理程序)。

您应该始终使用Task.WhenAll来执行多个异步方法并等待它们全部完成,而不是Parallel.Invoke

// Always let an async method return 'Task' or 'Task<T>' 
// and await it properly!
private async Task PlayBinAsync()
{
  InitBinList();

  if (animPlayingMode == AnimPlayingMode.ParallelSynchronous)
  {
    var runningTasks = new List<Task>();
    for (int i = 0; i < Products.Count; i++)
    {
      Task runningTask = ReadDisplayBinFrames(Products[i], true);
      runningTasks.Add(runningTask);

      Debug.WriteLine($"LedProducts Count: {Products[i].LastFrameRead} of Product {i}");
    }

    await Task.WhenAll(runningTasks);
    return;
  }

  for (int i = 0; i < Products.Count; i++)
  {
    await ReadDisplayBinFrames(Products[i], true);
      runningTasks.Add(runningTask);

      Debug.WriteLine($"LedProducts Count: {Products[i].LastFrameRead} of Product {i}");
  }
}   

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM