简体   繁体   中英

Load WPF Image List async, in specific order

I have a list of image paths which I need to update a UI with in an async manner:

foreach (string path in paths) {
    Task.Run(x => {
        var bitmap = getBitmap(path);
        Dispatcher.BeginInvoke((Action)() => Images.Add(new Image() { Source = bitmap; }));
    }); 
}

This works great, except that the order my images are added aren't necessarily the order in which they exist in the list of paths (this is expected behavior, or course, though not desired behavior).

Is there a way to run a loop of tasks in such a manner that one task does not complete until the prior task is completed?

I don't really care about the getBitmap queue order, but I want the Dispatch to happen in the same order as they're called per the paths list.

If I can't control the order of each Dispatch invocation itself, is there a way I can order the tasks themselves so that one doesn't run until the prior one is complete?

Assuming you are already on the UI thread, and you just want to prevent getBitmap from running on the UI thread and blocking, the best and simplest way would be to use async / await which will save you the need to call Dispatcher.BeginInvoke too.

You code would look like this:

foreach (string path in paths) {        
    var bitmap = await Task.Run(() => getBitmap(path));
    Images.Add(new Image { Source = bitmap });
}

Alternatively if this is not an option, you could use PLINQs .AsParallel().AsOrdered() like so:

var bitmaps =
  paths.AsParallel()
       .AsOrdered()
       .Select(getBitmap)

foreach (var bitmap in bitmaps)
{
    Dispatcher.BeginInvoke((Action)() => Images.Add(new Image { Source = bitmap }));
}

But remember that you lose some of the benefits of parallelism when retaining order.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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