Как запустить один процесс для нескольких значений в C #? - PullRequest
1 голос
/ 11 апреля 2019

Мне нужно запустить один процесс для списка символов. Итак, у меня есть список символов, таких как AAPL, FB, QQQ, MSFT, IBM, а также у меня есть функция, которая содержит логику вычислений для данного символа. Так что выполняйте эту логику, я использую задачу.

List<string> symbolList = new List<string>() {"AAPL","QQQ","FB","MSFT","IBM"};
Task[] taskArray = new Task[symbolList.Count];
for(int i=0; i<taskArray.Length; i++)
{
   taskArray[i] = Task.Factory.StartNew(() =>
       {
          criteriaEvalution.Evaluate(finalArray, false, new List<parseObj>(), ref builder, symbolList.IndexOf(i));
       });
}
Task.WaitAll(taskArray);

Итак, когда я запускаю этот код, он показывает мне ошибку, как

Индекс был вне диапазона. Должен быть неотрицательным и меньше размера коллекции.

Ошибка отображается в строке:

criteriaEvalution.Evaluate(finalArray, false, new List<parseObj>(), ref builder, symbolList.IndexOf(i));

где я собираюсь передать имя символа функции.

Так, пожалуйста, могу ли я получить решение для этого? Я проверил на Google это говорит, что индекс находится вне диапазона. Я проверил установленным отладчиком, но я не понимаю, как проверить его для областей задач.

Ответы [ 4 ]

1 голос
/ 11 апреля 2019

Во-первых, я бы использовал параллельную коллекцию ConcurrentBag в этом случае (если вы пишете в коллекцию). Параллельные коллекции блокируют экземпляр, когда несколько потоков собираются получить к нему доступ. Также я бы предложил использовать Task.WhenAll с ключевым словом await. Task.WaitAll может создать тупик. Вот пример, который вы можете попробовать:

public static async Task Main()
{
    var symbolList = new ConcurrentBag<string> { "AAPL", "QQQ", "FB", "MSFT", "IBM" };
    var taskArray = new List<Task>();

    foreach (var s in symbolList)
    {
        var task = Task.Run(() =>
        {
            Process(s);
        });

        taskArray.Add(task);
    }

    await Task.WhenAll(taskArray);
}
1 голос
/ 11 апреля 2019

Parallel.Foreach может сделать это. Вот пример как:

public static void DoIt(string a)
{
    Console.WriteLine(a);
}

public static void Main(string[] args)
{
    List<string> symbolList = new List<string>() { "AAPL", "QQQ", "FB", "MSFT", "IBM" };
    Parallel.ForEach(symbolList, a => DoIt(a));
}

Вы можете контролировать вызов, используя ParallelOptions:

ParallelOptions options = new ParallelOptions() { MaxDegreeOfParallelism = 10 };
Parallel.ForEach(symbolList, options, a => DoIt(a));
0 голосов
/ 12 апреля 2019

Помимо того, что у вас есть недопустимый код (symbolList.IndexOf(i), вероятно, должно быть symbolList[i]), проблема, с которой вы сталкиваетесь, заключается в том, что вы не захватываете переменную цикла перед вызовом лямбды.

Вот простое исправление:

List<string> symbolList = new List<string>() { "AAPL", "QQQ", "FB", "MSFT", "IBM" };
Task[] taskArray = new Task[symbolList.Count];
for (int i = 0; i < taskArray.Length; i++)
{
    string symbol = symbolList[i];
    taskArray[i] = Task.Factory.StartNew(() =>
    {
        criteriaEvalution.Evaluate(finalArray, false, new List<parseObj>(), ref builder, symbol);
    });
}
Task.WaitAll(taskArray);

Обратите внимание на строку string symbol = symbolList[i]; перед запуском задачи.

Если вы не сделаете этого, цикл завершится до запуска задач, а затем i будет равен taskArray.Length, и, следовательно, вы получите ошибку «Индекс был вне диапазона».

Еще одно, что я хотел бы предложить, это то, что вы должны использовать Microsoft Reactive Framework (он же Rx) - NuGet System.Reactive и добавить using System.Reactive.Linq; - тогда вы можете сделать это:

List<string> symbolList = new List<string>() { "AAPL", "QQQ", "FB", "MSFT", "IBM" };

var query =
    from symbol in symbolList.ToObservable()
    from e in Observable.Start(() =>
        criteriaEvalution.Evaluate(finalArray, false, new List<parseObj>(), ref builder, symbol))
    select e;

query.ToArray().Wait();

Гораздо проще и чище, чем задачи. Тогда вы также можете использовать операторы LINQ для результатов.

0 голосов
/ 11 апреля 2019

Возможно, вам следует заменить:

symbolList.IndexOf(i)

... на:

symbolList[i]
...