0

私は.Net4.0C#Windowsサービスベース(Dropboxのような)アプリケーションを開発しています。このアプリケーションは継続的に実行され、コンテンツと更新を特定のフォルダーで監視し、データベースに変更を通知します。同様のクライアントアプリケーションは他のマシンにもインストールされます。これにより、ホスティングマシンの同じフォルダに対して適切な更新が実行されます。私は、複数のスレッドと再帰呼び出しを使用してアプリケーション全体を開発しました。これにより、変更の実行と通知が継続されます。アプリケーションは、3時間後に3時間正常に実行され、スタックオーバーフロー例外がスローされてクラッシュします。

具体的には、9つのスレッドがあり、そのうちのいくつかは次の仕事をします

1)threadFSWToDB-ファイルの変更(追加、名前の変更、削除)をDBに書き込みます。

2)threadDBToUploadLogList-他のクライアントがファイルをダウンロードするサーバー上にフォルダーを作成します。

3)threadDoUpload-Webサーバーにファイルをアップロードします。

4)threadDBToDownloadList-DBのポーリングによって実行される変更のリストをアップロードします。

私の質問は、これが実行可能な解決策なのか、それともアプリ全体のデザインを再検討する必要があるのか​​ということです。はいの場合、上記のタスク(順次または並列)を実行するための最良の方法は何でしょうか。そして、このような本質的に終わりがなく継続的なタスクを実行するための最も基本的なアプローチは何ですか。

私のコードは以下の通りです、それが問題を明確にすることができるように私はどれだけ入れるべきかわかりません

Thread threadFSWToDB = new Thread(() => WriteFSWLogListToDatabase());


private static void WriteFSWLogListToDatabase()
    {
        try
        {
            using (var objEntities = new ShareBoxEntities()) // EF class instantiation
            {
// this DB class constructor call later on throws stack overflow exception not necessarily from this method
                var objConnector = new DBConnector(objEntities); 
                var objConnector = new DBConnector();
                List<string> directories = objConnector.GetAllSharedDirectoryRelativePaths();
                if (FSWLogList != null && FSWLogList.Count() > 0)
                {
                    for (int i = 0; i <= FSWLogList.Count - 1; i++)
                    {

            // some file changes being written to Database
                            FSWLogList[i].SavedInDB = true;
                        }
                    }
                }
            }
        }
        catch (Exception ex)
        {
    // write to event log and mail to administrator
        }
        finally
        {
            if (FSWLogList != null && FSWLogList.Count > 0)
            {
                FSWLogList.RemoveAll(item => item.SavedInDB == true);
            }
            Thread.Sleep(5000);
            WriteFSWLogListToDatabase();
        }
    }

再帰が主な理由である場合、アプリケーションが1日か2回正常に実行され、その後上記の動作を示し始める理由

4

3 に答える 3

0

詳細を知らずに言うのは難しいですが、スタックオーバーフローエラーは通常、再帰に深く入りすぎていることを意味します

簡単な例

public void ThrowStackOverflow()
{
    ThrowStackOverflow()
}

再帰への出口がないため、常にスタックオーバーフローが発生します。コールスタックは、スペースがなくなるまでどんどん深くなっていきます。

あなたのプログラムにも同様の自己参照主義の問題があるのではないかと思います。

巻き戻す前に深くなりすぎる可能性のある再帰呼び出しがある場合、スタックオーバーフローのリスクがあります。

または、スレッドが終了せずに自分自身を作成する場合、またはクリーンアップせずに新しいスレッドを作成し続ける場合でも、必然的に何かが発生します。

于 2012-09-12T17:41:13.000 に答える
0

あなたがスレッドを幸せにしているように私には聞こえます。DBの場合、スレッドのない非同期dbのBeginExecuteNonQueryがあります。DBから通知を受け取るには、クエリ通知があります。ファイルの場合、FileSystemWatcherがあります。BackGroundWorkerを使用してファイルをアップロードおよびダウンロードします。1つのサーバーにアップロード/ダウンロードする場合、帯域幅によって制限される可能性が高いため、ファイルを並行して実行しても効果はありません。

于 2012-09-12T21:16:40.350 に答える
0

貴重な時間をありがとうございました。

私は自分の問題の解決策を見つけました。再帰関数呼び出しはwhile(true)に置き換えられました//ループ はまだそれぞれのスレッドで呼び出されていますこれにより、フォルダーを監視する関数が実行を完了しないようにします例外が発生した後でも確実に実行されるように、キャッチしてみてください。while(true)を使用しているときに直面した問題は、関数で使用されるリソースを別のスレッドで実行されている他の関数で使用できるようにすることでした。これは、thread.sleepを特定の期間呼び出すことで処理されました。これは、同様の問題に対する普遍的な解決策ではないかもしれませんが、私の要件に適合しているので、同様のシナリオで前述の解決策を実装する前に、他の人に注意してもらいたいと思います。

于 2012-10-09T12:04:48.290 に答える