2

サービス ロジックの WCF レイヤーと対話する ASP.NET MVC 3 アプリケーションがあります。ある特定の機能では、サービス層が応答するのに時間がかかり、UI は svc でタイムアウトします。処理自体が膨大なので、どうしても時間がかかります。ユーザーに timeout を見せたくないので、部分的な成功ステータスを表示し、UI をステータスで更新し続けることを計画しました。

プロセスをさまざまなステップに分割する予定です。そのうちのいくつかは、ファイヤー アンド フォーゲット ファッションのようなものです。ユーザーが詳細を要求したとき

  1. Svc は必須の手順を処理し、応答を返します

  2. Svc はまた、以下 (TPL) を使用してタスクを起動します。これにより、必須ではない手順が実行されます。

    Task.Factory.StartNew(FireAway);
    
  3. UI はステータスを更新するためにポーリングを続けます

  4. タスクは DB の完了ステータスを更新します

  5. UI は完了ステータスをポーリングして取得し、UI に表示します

懸念...

  1. タスクを処理するスレッドは再利用されますか (リスナーがアタッチされていません)、これによりスレッドの作成やリークが多すぎますか?
  2. リソースについてはどうですか? ファイア アンド フォーゲット タスクはメモリ リークを引き起こしますか? タスク機能は、複数の DB に接続してステータスを更新することです。
  3. 私はデザインに満足していません (私たちはこれを迅速な修正として行う必要があります)、より良いデザインパターンはありますか?
4

2 に答える 2

1

マルシンは正しいです。私はその答えに賛成しましたが、説明する必要があると思いました。TPL 自体は、リソースのリークを引き起こしません。リソース リークが発生した場合は、この記事をお読みください。:-)

Marcin は、IIS が AppPool をリサイクルして「データ損失」を引き起こす可能性についても正しいです。同様のシナリオがあり、それが予想以上に頻繁に発生することがわかりました。「ねえ、データベースであなたを待っているデータがあります」というトリガーメッセージを受け取るように、サービスを少し再設計しました。これにより、ポーリングの必要がなくなります。実行される機能は複数ステップのプロセスであり、各ステップでデータベースが更新されるため、サービスが途中で再開/リサイクルされた場合、中断したところから再開できます。これを Windows サービスに変換する必要はありませんが、別の非 Web サーバーに移動したい場合、または移動する必要がある場合は可能です。

あまりにも多くのスレッドがスプールされることが心配な場合は、この SO Q&Aを確認してください。

教育上の注意: async と fire-and-forget は同じではありません。非同期とは、「答えが欲しいのですが、待ちきれないので、終わったら後で電話してください」という意味です。Fire-and-forget とは、「ここにいくつかのデータ/情報があります。それを使用してください。ただし、私に電話しないでください。気にしないか、知りたい場合は後で電話をかけます。」という意味です。

于 2013-11-27T14:18:11.500 に答える
1

まずは作成から

Task.Factory.StartNew(FireAway);

新しいスレッドを明示的に作成しません。そのタスクはスレッド プールのスレッドを使用しますが、タスクからスレッドへの 1:1 マッピングはありません。たとえば、タスクが I/O 操作に長時間を費やす場合、基になるスレッドを別のリクエストで使用できます。

すべてを正しく行っていれば、指定した設計によってリソース (スレッドまたはメモリ) のリークが発生することはありません。技術的な観点からの設計は正しいですが、大幅に改善することができます。

この設計では、実行中に IIS の再起動によってこのタスクが強制終了される傾向があります。より良いアプローチは、Web リクエストでリクエスト情報をデータベースに保存し、バックエンドの Windows サービスでそれを取得して処理することです。UI は、特定のタスクの更新についてデータベースをチェックするだけで済みます。

于 2013-10-29T09:43:33.807 に答える