Reputation: 77
I have an app where I select multiple (300-500) images then create a video where each image is a frame. In order to load these images into a composition for playback, I need to convert them and save them to temporary memory before they can be loaded. This conversion/save process is taking some time and I'm trying to find ways to speed up the task.
What would be a good way to have multiple instances of this conversion task take place in parallel? Currently, CPU usage is low (4%-6%) while the conversion is taking place.
Here is how I'd like it to work:
User picks multiple image files
A folder in temporary storage is created
Multiple image convert/save tasks are created and run in parallel.
After conversion and save is complete, all converted images in temporary storage folder are selected and loaded into a composition for playback.
Here's what I have now:
private async Task OpenImageSequence(IReadOnlyList<StorageFile> files)
{
destFolder = await ApplicationData.Current.TemporaryFolder.CreateFolderAsync(NameNoExt, CreationCollisionOption.GenerateUniqueName);
var composition = new MediaComposition();
foreach (StorageFile file in files)
{
CreateImage(file);
}
IReadOnlyList<StorageFile> fileList = await destFolder.GetFilesAsync();
foreach (StorageFile imgFile in fileList)
{
var clip = await MediaClip.CreateFromImageFileAsync(imgFile, TimeSpan.FromSeconds(frameIncrement));
composition.Clips.Add(clip);
}
MediaStreamSource newImageSequence = composition.GenerateMediaStreamSource(defaultProfile);
windowsSource = MediaSource.CreateFromMediaStreamSource(newImageSequence);
}
private async Task CreateImage(StorageFile file)
{
var stream = await file.OpenStreamForReadAsync();
//....Image Conversion Code....//
var destFile = await destFolder.CreateFileAsync("exrConvert.png", Windows.Storage.CreationCollisionOption.GenerateUniqueName);
await canvas.SaveAsync(destFile.Path.ToString(), CanvasBitmapFileFormat.Png);
}
Basically I'd like to have as many instances of the the CreateImage task running in parallel as possible. Any thoughts as to how I go about doing this?
I tried the following for a selection of 10 images but the images did not seem to be processed in parallel:
Task t1 = CreateImage(files.ElementAt(0));
Task t2 = CreateImage(files.ElementAt(1));
Task t3 = CreateImage(files.ElementAt(2));
Task t4 = CreateImage(files.ElementAt(3));
Task t5 = CreateImage(files.ElementAt(4));
Task t6 = CreateImage(files.ElementAt(5));
Task t7 = CreateImage(files.ElementAt(6));
Task t8 = CreateImage(files.ElementAt(7));
Task t9 = CreateImage(files.ElementAt(8));
Task t10 = CreateImage(files.ElementAt(9));
await Task.WhenAll(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10);
Thanks for any help you can provide!
Upvotes: 0
Views: 423
Reputation: 2651
To let multiple tasks run in parallel, each task have to be composed as a background task. So you need to use Task.Run() or something. Plain async function with Task return type does not yield background task.
//foreach (StorageFile file in files)
//{
// await CreateImage(file);
//}
var tasks_in_background_thread = files.Select(file => Task.Run(async () =>
{
await CreateImage(file);
}));
await Task.WhenAll(tasks_in_background_thread);
Upvotes: 1