簡體   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