繁体   English   中英

如何在C#中为多个值运行单个进程?

[英]How to run single process for multiple values in c#?

我需要为符号列表运行单个过程。 因此,我有一个符号列表,如AAPL,FB,QQQ,MSFT,IBM,而且我还有一个函数,其中包含给定符号的计算逻辑。 因此,请执行我使用Task的逻辑。

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上检查过,这是因为索引超出范围。 我已经通过设置调试器进行了检查,但是我不明白如何检查任务区域。

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

首先,在这种情况下(如果您写入集合),我将使用并发集合ConcurrentBag 当多个线程将要访问实例时,并发集合将锁定该实例。 另外,我建议将Task.WhenAllawait关键字一起使用。 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);
}

可能您应该替换:

symbolList.IndexOf(i)

...有:

symbolList[i]

除了您有非法代码( symbolList.IndexOf(i)应该是symbolList[i] )的事实之外,您面临的问题是在调用lambda之前没有捕获循环变量。

这是简单的解决方法:

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(aka Rx)-NuGet System.Reactiveusing System.Reactive.Linq;添加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运算符。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM