【发布时间】:2019-01-29 22:43:53
【问题描述】:
我正在制作资源加载代码。但是,有一个问题。
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 函数完成。但是,由于异步操作委托,我没有等待。这表明
并行加载开始
加载音频
加载音频
加载图片
加载音频
加载图片
...
加载音频
并联负载端
加载图片
加载图片
加载图片
...
没有同步加载图像的方法,因为它是 Win2D 的一部分。 (= WinRT API)
我明白为什么所有磁盘 I/O 任务都必须是异步方法。
但是,上面的代码不是在 UI 线程而是在自定义线程上运行的。所以,它不需要异步运行。
您可以认为 Parallel 由于 async 方法而无用。但是,如您所见,toDoValues 既有异步(Win2D),也有同步(音频)。有效加载音频文件需要并行。
如何让 Parallel 等到所有资源都加载完毕?
【问题讨论】:
-
是的,你是从错误的角度来的,只是使用了任务,然后使用
WhenAll或WaitAll等待它们 -
您的问题与 Parallel 无关。并行等待,直到所有的动作都被执行。您启动异步任务,不要等到它们完成。
-
您的一些操作本身就是
async,因为没有返回Task,您有“即发即弃”的操作。该操作将在任务开始时完成,而不是在完成时完成。此类操作不直接适合与同步操作一起安排:要么全部为Func<..., Task<T>>,要么全部同步。 -
我明白为什么会这样。我知道 Parallel 正在等待所有任务。但是,任务是异步方法。异步方法一调用就返回。因此,Parallel 认识到所有任务都返回并完成了。所以,我使用了 SemaphoreSlim (init 0, max 1)。并在并行后等待,并在加载所有资源时唤醒。它运作良好。但是,代码似乎很脏。
-
我发布这个问题是因为 Win2D LoadAsync 方法没有任何同步方法。我昨天尝试了 LoadAsync -> Wait -> Result。但是,它会抛出 ArgumentException。但是,当我刚才再次尝试时,它起作用了! ???于是,就解决了。感谢所有 cmets!
标签: c#