数百から数千の行を含むテキスト ファイルから読み取るアプリケーションがあります。
各行は、ParallelOptions を使用して parallel.foreach を使用して処理され、実行されるタスクの量を制限します。これが「コントローラー」タスクです。
この「コントローラー」内には、実際の作業を実行する別の parallel.foreach があります。起動された各コントローラ タスクは、元のファイル行で指定された異なるデータ入力で同じ作業を実行します。この作業でも、parallel.foreach は paralleloptions を使用して、実行されるタスクの量を制限しています。
前回のテストでは、Controller foreach: MaxDegreeOfParallelism=4 を使用しました。 Worker foreach: MaxDegreeOfParallelism:4
私の計算によると、一度に最大 16 個のタスクが動作することを意味するはずです。
しかし、perfmon.exe を確認すると、アプリケーションが 700 スレッドを使用していることがわかります。さらに数時間後には 1000 を超えます。
どうすればいいの?GC がこれらの終了したスレッドを収集しないのはなぜですか?
以前、私のコードは同じ問題で Thread[] 内の実際のスレッドを起動していました。次に、それを Task[] に移動しましたが、同じ問題がありました。どこかにスレッドリークがあり、参照がまだスレッド/タスクを指していると思いました。これを探すのに何時間も費やしましたが、役に立ちませんでした。
したがって、タスクへの参照が作成されていない場合、すべてラムダ内で発生するため、タスクリークは発生しないという考えで、parallel.foreach に移行しました。
しかし、問題は解決しません。これがなぜなのかについてのアイデアはありますか?それとも正常ですか?
以下のコードを追加しました。すべてのテストが原因で少しごちゃごちゃになっており、この問題をデバッグしようとして、少しクリーンアップしようとしました。
public static void RunActions(
List<paramsActionSettings> listActions,
string[] arrList,
int numThreads,
string domain = null,
delGetParamsActionSettings delGetActionsList = null,
delProcessString callbackActionsComplete = null
)
{
int iCntr= 0;
int iTotal = arrList.Length;
ParallelOptions prlOptions = new ParallelOptions
{
MaxDegreeOfParallelism = numThreads
};
//foreach (string listItemIter in arrList)
object oLock = new object();
Parallel.ForEach(arrList, prlOptions,(listItemIter) =>
{
lock (oLock)
{
Console.WriteLine("starting "+iCntr + " of " + iTotal + " run actions");
iCntr++;
}
string listItemCopySafe = string.Copy(listItemIter);
bool bCanDo = true;
List<paramsActionSettings> listActionsUse;
if (listActions == null)
{
listActionsUse = delGetActionsList();
}
else
{
listActionsUse = listActions;
}
foreach (paramsActionSettings prms in listActionsUse)
{
if (prms.delCanDo != null && !prms.delCanDo(listItemCopySafe, domain))
{
bCanDo = false;
break;
}
}
if (!bCanDo) return;
List<paramsFire> listParams = new List<paramsFire>();
//create a list of paramsfire objects, the object holds the params and the delfunction
foreach (paramsActionSettings prms in listActionsUse)
{
listParams.Add(new paramsFire(prms.delGetDoParams(listItemCopySafe), prms.delDoSomething));
}
FireActions(listParams, callbackActionsComplete, listItemCopySafe);
Console.WriteLine("Finished " + iCntr + " of " + iTotal );
});
}
private static void FireActions(List<paramsFire> list, delProcessString callbackActionsComplete, string itemArr)
{
int icntr = 0;
foreach (paramsFire prms in list)
{
try
{
if (icntr == 0)
{
if (!prms.delDoSomething(prms.oParams))
{
break;
}
}
else
{
prms.delDoSomething(prms.oParams);
}
icntr++;
}
catch (Exception e)
{
ErrorLog.WriteLine("foreach (paramsFire prms in list)");
UtilException.Dump(e, "foreach (paramsFire prms in list)");
}
}
if (callbackActionsComplete != null)
{
try
{
callbackActionsComplete(itemArr);
}
catch { }
}
}