Task - Property Assignment

匆匆过客 提交于 2019-12-24 06:27:21

问题


Originally, I had the following:

foreach (Product product in products)
{
    product.ImageUri = _imageClient.GetImageUri(product.GetImagePath());
}

What I would like to do is process all of the Products in parallel rather than one at a time. I have updated _imageClient.GetImageUri(...) to _imageClient.GetImageUriAsync(...). I can now do the following:

List<Task<Uri>> tasks = new List<Task<Uri>>();

foreach (Product product in products)
{
    Task<Uri> task = _imageClient.GetImageUriAsync(product.GetImagePath());
    tasks.Add(task);
}

var results = await Task.WhenAll(tasks);

The problem I have with this approach is that I now have to loop through the results, match each to the correct Product and assign the property.

Is there a way to combine the two approaches so that I can perform the property assignment as part of the task so that all can be run in parallel?


回答1:


What about:

    List<Task<Uri>> tasks = new List<Task<Uri>>();

    foreach (Product product in products)
    {
        tasks.Add(Task.Run( async () =>  product.ImageUri = await _imageClient.GetImageUriAsync(product.GetImagePath()) ));
    }

    await Task.WhenAll(tasks);    

You don't even really need the results in the end.




回答2:


you could start them also in a single select statement and await them in the same line:

await Task.WhenAll(products.Select(async p => p.ImageUri = await _imageClient.GetImageUriAsync(p.GetImagePath())));

This will execute all tasks in parallel and initialize the property. Task.WhenAll will then wait for the slowest of them.

Here is a LINQPad Example to demonstrate the workings:

void Main()
{   
    Do();
}

public async Task Do()
{    
    List<Product> products = new List<UserQuery.Product>
    {
        new Product(),
        new Product(),
        new Product(),
        new Product(),
    };
    Stopwatch sw = new Stopwatch();
    Console.WriteLine("START");
    sw.Start();
    await Task.WhenAll(products.Select(async x => x.MyProperty = await GetNumber()));
    sw.Stop();
    Console.WriteLine($"ENDE: {sw.ElapsedMilliseconds}");       
    products.Dump();    
}

public async Task<int> GetNumber()
{
    Random rand = new Random(DateTime.Now.Millisecond);
    return await Task.Run(() => { System.Threading.Thread.Sleep(4000); return rand.Next(1,1000);});
}

class Product
{
    public int MyProperty { get; set; }
}

Output:



来源:https://stackoverflow.com/questions/57457470/task-property-assignment

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!