[英]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
方法必须始终返回Task
或Task<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.