thread.Join() вызывается раньше начала работы потока
В начале выполняется данный кусок кода:
List<Thread> listOfThreads = new List<Thread>(50);// 50 взято для примера
for (int i = 0; i < 50; i++)
{
listOfThreads.Add(new Thread(new ParameterizedThreadStart(voidForThreads)));
ParametersForThread parameters = new ParametersForThread()
{
// Некоторые параметры
};
listOfThreads[i].Start(parameters);
}
После:
foreach (var thread in listOfThreads)
{
thread.Join();
}
Код отрабатывает, метод, где создаётся 50 потоков, гордо возвращает null, а потом срабатывает breakPoint внутри voidForThreads. 50 раз подряд...
Если я правильно понимаю причину, то thread.Join(); вызывается раньше, чем потоки начинают свою работу. Чем такой недуг можно вылечить? Или причина и вовсе в другом?
UPD: Вот метод voidForThreads:
private async Task voidForThreads(object obj)
{
ParametersForThread parameters = (ParametersForThread)obj;
var request = new HttpRequestMessage(HttpMethod.Post, "site");
var getOrderRequest = new GetOrderRequest()
{
OrderIDArray = parameters.PackOrders,
};
string text = new XMLConverter().ConvertObjectToXMLString(typeof(GetOrderRequest), getOrderRequest);
request.Content = new StringContent(text);
var client = parameters._clientFactory.CreateClient();
HttpResponseMessage response = null;
try
{
response = await client.SendAsync(request: request);
}
catch
{
// тут немного другая логика, но в блок catch в данном методе я
// ещё ни разу не попадал - не думаю, что проблема в нём
throw new NotImplementedException();
}
// Метод отработал верно - я проверял
GetOrderResponse result = (GetOrderResponse)new XMLConverter().ConvertXMLStringToObject(typeof(GetOrderResponse), await response.Content.ReadAsStringAsync());
// private GetOrderResponseOrderArray[][] ResultList - приватное поле, объявлено заранее
ResultList[parameters.NumberInList] = new GetOrderResponseOrderArray[result.OrderArray.Length];
for (int i = 0; i < result.OrderArray.Length; i++)
{
// Логика немного упрощена - мне не весь массив результатов нужен, поэтому здесь
// поштучное копирование нужных полей
ResultList[parameters.numberInList][i] = result.OrderArray[i];
}
}
И также класс ParametersForThread:
private class ParametersForThread
{
public string[] PackOrders { get; set; }
public IHttpClientFactory _clientFactory { get; set; }
public int NumberInList { get; set; }
}
Ответы (1 шт):
Автор решения: Anatoly
→ Ссылка
Отдельная благодарность пользователям @aepot и @CrazyElf.
Код ниже хоть и не даёт ответа на вопрос "Почему thread.Join() отработал раньше старта работы потоков?", - но решает мою проблему:
public class MainClass
{
private GetOrderResponseOrderArray[][] ResultArray { get; set; }
// Конструкция List<string[]> listOfPackOrders вызвана ограничениями используемых API
public async Task MainMethod(IHttpClientFactory _clientFactory, List<string[]> listOfPackOrders)
{
if (_clientFactory is null)
{
throw new ArgumentNullException(nameof(_clientFactory));
}
if (listOfPackOrders is null)
{
throw new ArgumentNullException(nameof(listOfPackOrders));
}
ResultArray = new GetOrderResponseOrderArray[listOfPackOrders.Count][];
Task[] arrayOfTasks = new Task[listOfPackOrders.Count];
for (int i = 0; i < listOfPackOrders.Count; i++)
{
ParametersForThread parameters = new ParametersForThread()
{
NumberInList = i,
PackOrders = listOfPackOrders[i],
_clientFactory = _clientFactory
};
arrayOfTasks[i] = Task.Run(async () => { await TaskForTaskArray(parameters); });
}
Task.WaitAll(arrayOfTasks);
// Дальнейшая работа с ResultArray
}
private async Task TaskForTaskArray(ParametersForThread parameters)
{
var request = new HttpRequestMessage(HttpMethod.Post, "site");
var getOrderTransactionsRequest = new GetOrderTransactionsRequest()
{
OrderIDArray = parameters.PackOrders;
};
string text = new XMLConverter().ConvertObjectToXMLString(typeof(GetOrderTransactionsRequest), getOrderTransactionsRequest);
request.Content = new StringContent(text);
var client = parameters._clientFactory.CreateClient();
HttpResponseMessage response = null;
try
{
response = await client.SendAsync(request: request);
}
catch
{
// тут немного другая логика, но в блок catch в данном методе я
// ещё ни разу не попадал - не думаю, что проблема в нём
throw new NotImplementedException();
}
GetOrderResponse result = (GetOrderResponse)new XMLConverter().ConvertXMLStringToObject(typeof(GetOrderResponse), await response.Content.ReadAsStringAsync());
ResultList[parameters.NumberInList] = new GetOrderResponseOrderArray[result.OrderArray.Length];
for (int i = 0; i < result.OrderArray.Length; i++)
{
// Логика немного упрощена - мне не весь массив результатов нужен, поэтому здесь
// поштучное копирование нужных полей
ResultList[parameters.numberInList][i] = result.OrderArray[i];
}
}
private class ParametersForThread
{
public string[] PackOrders { get; set; }
public IHttpClientFactory _clientFactory { get; set; }
public int NumberInList { get; set; }
}
}