我正在制作资源加载代码。但有个问题。
var toDoList = new List<Action>();
toDoList.Add(async () =>
{
await CanvasBitmap.LoadAsync(PATH1);
Console.WriteLine("Load image");
});
toDoList.Add(async () =>
{
await CanvasBitmap.LoadAsync(PATH2);
Console.WriteLine("Load image");
});
// ...
toDoList.Add(async () =>
{
await CanvasBitmap.LoadAsync(PATH100);
Console.WriteLine("Load image");
});
toDoList.Add(() =>
{
AudioSystem.Instance.Load(AUDIO_PATH1);
Console.WriteLine("Load audio");
});
toDoList.Add(() =>
{
AudioSystem.Instance.Load(AUDIO_PATH2);
Console.WriteLine("Load audio");
});
// ...
toDoList.Add(() =>
{
AudioSystem.Instance.Load(AUDIO_PATH100);
Console.WriteLine("Load audio");
});
Console.WriteLine("Parallel Load Start");
Parallel.ForEach(toDoList, toDo => {
toDo();
});
Console.WriteLine("Parallel Load End");
我想让Parallel等待所有LoadAsync函数完成。但是,由于异步Action委托,我没有等待。它表明
并行加载开始
加载音频
加载音频
加载图像
加载音频
加载图像
...
加载音频
并行加载结束
加载图像
加载图像
加载图像
...
由于它是Win2D的一部分,因此无法同步加载图像。(= WinRT API)
我理解为什么所有磁盘I / O任务都必须是异步方法。
但是,以上代码不是在UI线程上运行,而是在自定义线程上运行。因此,它不需要运行异步。
您可以认为,由于异步方法,并行是无用的。但是,如您所见,toDoValues同时具有异步(Win2D)和同步(音频)。需要并行以有效加载音频文件。
如何让Parallel等待所有资源加载完毕?
需要并行以有效加载音频文件。
好吧,这Parallel
是进行并行操作的一种方法。但是您的代码当前正在混合CPU绑定的操作和异步操作,并尝试使用进行合并Parallel
,这仅适用于CPU绑定的操作。这就是为什么效果不佳的原因。
更好的方法是使用Task.Run
而不是将CPU绑定的操作推送到线程池上Parallel
。然后,您可以将它们视为异步的(从UI线程的角度来看),然后使用将它们与自然异步的I / O操作结合起来Task.WhenAll
。
使用示例代码,它看起来像这样:
var toDoList = new List<Func<Task>>();
toDoList.Add(async () =>
{
await CanvasBitmap.LoadAsync(PATH1);
Console.WriteLine("Load image");
});
toDoList.Add(async () =>
{
await CanvasBitmap.LoadAsync(PATH2);
Console.WriteLine("Load image");
});
// ...
toDoList.Add(async () =>
{
await CanvasBitmap.LoadAsync(PATH100);
Console.WriteLine("Load image");
});
toDoList.Add(() => Task.Run(() =>
{
AudioSystem.Instance.Load(AUDIO_PATH1);
Console.WriteLine("Load audio");
}));
toDoList.Add(() => Task.Run(() =>
{
AudioSystem.Instance.Load(AUDIO_PATH2);
Console.WriteLine("Load audio");
}));
// ...
toDoList.Add(() => Task.Run(() =>
{
AudioSystem.Instance.Load(AUDIO_PATH100);
Console.WriteLine("Load audio");
}));
Console.WriteLine("Concurrent Load Start");
var tasks = toDoList.Select(toDo => toDo()).ToList();
Console.WriteLine("Concurrent Load Started");
await Task.WhenAll(tasks);
Console.WriteLine("Concurrent Load End");
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句