Stack.Overflowエラー-WinForms App Vs. WinService
-
06-07-2019 - |
質問
小さなコードサンプルがあります:
private void MonitorItems()
{
if (someCondition)
{
dateSelected = DateTime.Now;
GetAllItems();
}
else
{
if(allItems.Count>0)
CheckAllItems();
}
MonitorItems();
}
メソッドGetAllItemsはDBに移動し、コレクションのすべての新しいアイテムを取得します->全てのアイテム。 次に、CheckAllItemsメソッド:
private void CheckAllItems()
{
foreach (Item a in new List<Item>(allItems))
{
switch (a.Status)
{
case 1:
HandleStatus1();
break;
case 2:
HandleStatus2(a);
break;
case 0:
HandleStatus0(a);
break;
default:
break;
}
}
}
場合によっては(HandleStatus1およびHandleStatus2で)DBにアクセスし、更新を行ってから、メソッドallAllsを呼び出すことでコレクションallItemsを再度作成する必要があります。
このタイプのコードは、WinFormsAppでStack.Overflow例外をスローしています。
2つの質問があります。
1.このタイプの例外は、同じコードを使用してWinServiceアプリケーションでスローされますか?
2.自己呼び出し方式の代わりにタイマーを使用することについて、あなたの意見はどうですか?
解決
「自己呼び出し方法」 &quot;再帰メソッド&quot; と呼ばれます。あなたのソリューションは創造的です、私はあなたにそれをあげます。しかし、それをしないでください。スタックスペースは非常に限られています。サービスに移動するとこの問題が発生しますが、これを処理するためのはるかに優れた方法があります。サービスで使用する場合、タイマーは非常に適切です。
他のヒント
あなたのケースでメソッドを再帰的に呼び出すのは、タイマーを使用して行うのと同じくらい悪いです。どちらもしないでください!!
単純なループを使用し、スレッドをしばらくの間スリープさせます。
MS ILには.tail opコードがあります。しかし、c#ドットは末尾再帰を認識したい(。ところで、末尾再帰は.netでは非常に遅い((
なぜ再帰する必要があるのですか?メソッドが再帰を停止してチェーンを終了できるようにするフロー制御ステートメントはありません。無限再帰がおそらくオーバーフローの原因です。より良い解決策は、再帰を完全に廃止することです。 elseラッパーを削除すると、再帰することなく同じ結果が得られます。
private void MonitorItems()
{
if(someCondition)
{
dateSelected = DateTime.Now;
GetAllItems();
}
if(allItems.Count>0)
CheckAllItems();
}
これにより、ループに陥ることなく同じ結果が得られます。次に、実行環境のコンテキストで呼び出しを繰り返すルールを実装できます。フォームのボタンをクリックするか、サービスアプリケーションのタイマーをクリックします。