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).