Получение ошибки Аргумент задач содержит нулевое значение.Имя параметра: задачи в параллельной библиотеке задач с параллельным. - PullRequest
0 голосов
/ 13 февраля 2019

Я пытаюсь выполнить несколько задач, которые внутренне вызывают некоторые вызовы http.Проблема в том, что когда я использую цикл Parallel.ForEach, я получаю сообщение об ошибке:

Аргумент задач содержит нулевое значение.Имя параметра: задачи

List<Task> TskList = new List<Task>();

Parallel.ForEach(dt.AsEnumerable(), row =>
//foreach (DataRow row in dt.Rows)
{

    var oTsk =
        new Task(
            () =>
            {
                try
                {
                    some http call
                }
                catch (Exception ex)
                {

                    //AppendTextBox(row["ssub_msisdn"] as string + ", Error: " + ex.Message, txtBoxResponse);
                }
            });
    TskList.Add(oTsk);
    oTsk.Start();
}
);

var t = Task.WhenAll(TskList.ToArray());
try
{
    await t;
}
catch { }

if (t.Status == TaskStatus.RanToCompletion)
{
    SetLabel("Completed", lblProcessingStatus);
}
else if (t.Status == TaskStatus.Faulted)
{ SetLabel("Faulted", lblProcessingStatus); }

1 Ответ

0 голосов
/ 13 февраля 2019

Вы пытаетесь получить доступ к списку TskList из разных потоков без какой-либо синхронизации.Это может привести к любым проблемам.

Просто сделайте это:

var tasks = dt.AsEnumerable().Select(row => Task.Run(() =>
    {
        try
        {
            // some http call
        }
        catch (Exception ex)
        {
            // rewrap the needed information into your custom exception object
            throw YourException(ex, row["ssub_msisdn"]);
        }
    });

// now you are at the UI thread
foreach (var t in tasks)
{
    try
    {
        await t;
    }
    catch (YourException ex)
    {
        AppendTextBox(ex.SsubMsisdn + ", Error: " + ex.InnerException.Message, txtBoxResponse);
    }
}

Task.Run запустит задачу в пуле потоков, вам на самом деле не нужно Parallel.ForEach.


На самом деле, если ваш код в try только выполняет http-вызов, вам вообще не нужен Task!Вы можете полностью избежать потоков, используя асинхронную версию, например, HttpClient.GetByteArrayAsync или HttpClient.GetStreamAsync + Stream.CopyToAsync.

E.г .: * 10101

HttpClient client = new HttpClient(); // maybe configure it

async Task ProcessRow(Row row) // put here the correct type
{
    try
    {
        var str = await client.GetStringAsync(row[address]);
        AppendTextBox(str, txtBoxResponse);
    }
    catch (HttpRequestException ex)
    {
        AppendTextBox(row["ssub_msisdn"] + ", Error: " + ex.Message, txtBoxResponse);
    }
}

var tasks = dt.AsEnumerable().Select(row => ProcessRow(row));
await Yask.WhenAll(tasks);
...