Home > Enterprise >  How to run parallel methods which returns different types?
How to run parallel methods which returns different types?

Time:11-27

I am creating app which will comunicate with API of shop. I have written around 30 classes representing requests to API and I am wondering how to run these request parallel.

I have tried to done it with List of tasks but it does not work beacouse of imprecise returning type of function.

For example these are request classes:

public class GetOrderStatusList : IRequest<GetOrderStatusList.Response> {
    public class Status {
        [JsonPropertyName("id")]
        public int Id { get; set; }

        [JsonPropertyName("name")]
        public string Name { get; set; }
    }

    public class Response : Output {
        [JsonPropertyName("statuses")]
        public List<Status> Statuses { get; set; }
    }
}
public class GetProductsPrices : IRequest<GetProductsPrices.Response> {
    [JsonPropertyName("storage_id")]
    public string StorageId { get; set; }

    public class Product {
        public class Variant {
            [JsonPropertyName("variant_id")]
            public int VariantId { get; set; }

            [JsonPropertyName("price")]
            public decimal Price { get; set; }
        }

        [JsonPropertyName("product_id")]
        public int ProductId { get; set; }

        [JsonPropertyName("price")]
        public decimal Price { get; set; }

        [JsonPropertyName("variants")]
        public List<Variant> Variants { get; set; }
    }

    public class Response : Output {
        [JsonPropertyName("storage_id")]
        public string StorageId { get; set; }

        [JsonPropertyName("products")]
        public List<Product> Products { get; set; }
    }
}

Output, IRequest and method which sends request to server:

public interface IRequest<TResponse> { }

public class Output {
    [JsonPropertyName("status")]
    public string Status { get; set; }

    [JsonPropertyName("error_message")]
    public string? ErrorMessage { get; set; }

    [JsonPropertyName("error_code")]
    public string? ErrorCode { get; set; }
}

public async Task<TResponse> SendRequestAsync<TResponse>(IRequest<TResponse> userRequest) where TResponse : Output {
        var client = new RestClient(_url);
        var method = GetRequestMethodName(userRequest);
        var request = CreateRequest(method, userRequest);
        var response = await ExecuteRequestAsync(client, request);
        var serializedResponse = JsonSerializer.Deserialize<TResponse>(response.Content);

        if( serializedResponse.Status == "ERROR") {
            throw new BaselinkerException(serializedResponse.ErrorMessage, serializedResponse.ErrorCode); 
        }

        return serializedResponse;
    } 

CodePudding user response:

Your list type doesn't make sense; it's trying to hold items of requests for outputs, but the method just returns outputs, not requests for outputs.

Your collection type should be List<Task<Output>>, or possibly just List<Task>.

CodePudding user response:

There is no nice and easy way to run multiple different tasks in a loop. Please note that this is not async/tasks specific problem: there also is no nice and easy way to run in a loop multiple non async methods that return different types.

Here's a toy example for running two tasks without waiting for one to finish before starting the next:

using System.Diagnostics;

var sw = Stopwatch.StartNew();

var t1 = F1();
var t2 = F2();


var n = await t1;
var s = await t2;

Console.WriteLine($"Elapsed {sw.ElapsedMilliseconds}");

async Task<int> F1()
{
    await Task.Delay(TimeSpan.FromMilliseconds(100));
    return 7;
}

async Task<string> F2()
{
    await Task.Delay(TimeSpan.FromMilliseconds(200));
    return "waves";
}

The elapsed time will be ~200ms (aka the time it takes for the slowest task to run), not 300ms (aka the sum of times of both tasks to run).

  • Related