10

Azure テーブルにすべてを格納する Logging ライブラリを構築しています。そのテーブルへの書き込みには明らかに時間がかかります (1 秒を超えることはありませんが、それでもユーザーを待たせるには長すぎます)。そのため、Log メソッドは LogResult インスタンスを返します。

public class LogResult
{
    public string Id { get; set; }
    public Task LoggingTask { get; set; }

    public LogResult(string id, Task task)
    {
        Id = id;
        LoggingTask = task;
    }
}

そして、これが Log メソッドがどのように終了するかです

return new LogResult(id, Task.Factory.StartNew(() => 
    DoLogInAzure(account, id, exception, request))
);

呼び出し元が完了するまで待機するオプションを提供するため (たとえば、コンソール アプリの場合)。私が直面している問題は、IISがユーザーに応答を返す前にそれを待つべきではないということです...そして、それを待たないと、IIS は常にタスクを実行するとは限りません。アイデアは、ユーザーにメッセージを表示することです。

IIS が応答を返した後でも、タスクが終了するまで強制的に待機させる方法はありますか? 要求を非同期で受け取る Windows サービスをコーディングする必要があるかもしれないと考えていますが、ログ エントリを追加するだけでも大変な作業のように見えます...特に IIS にそれを待機させることができる場合。

アイデアをありがとう!

4

4 に答える 4

12

Phil Hack によるこの投稿では、ASP.NET アプリケーションでのバックグラウンド タスクの実行について説明しています。

于 2012-09-30T23:03:10.463 に答える
10

Damian Schenkelman と Phil Haack のブログ投稿のおかげで、問題と解決策がわかりました。問題は、IIS が新しい要求を処理する必要があるときにスレッドを再利用することです。そして、私のタスクが何らかの作業を行っていることを認識していないため、そのスレッドを再利用します (これは理にかなっています)。次に、そのスレッドを使用していて再利用できないことを IIS に通知する必要があります (したがって、別のスレッドを再利用するか、新しいスレッドを作成するか、待機させる必要があります)。タスクの作成を処理し、IIS に通知機能を自動的に登録する独自の TaskFactory を使用することになりました。完全を期すために、私と同じ問題を抱えている他の人々を助け、別の提案を読むために、これが私がやったことです

public class IISNotifier : IRegisteredObject
{
    public void Stop(bool immediate)
    {
        // do nothing, I only run tasks if I know that they won't
        // take more than a few seconds.
    }

    public void Started()
    {
        HostingEnvironment.RegisterObject(this);
    }

    public void Finished()
    {
        HostingEnvironment.UnregisterObject(this);
    }
}

その後

public class IISTaskFactory
{
    public static Task StartNew(Action act)
    {
        IISNotifier notif = new IISNotifier();
        notif.Started();
        return Task.Factory.StartNew(() => {
            act.Invoke();
            notif.Finished();
        });
    }
}

さて、ログタスクを開始したいときは

return new LogResult(id, IISTaskFactory.StartNew(() => 
    DoLogInAzure(account, id, exception, request))
);

https://github.com/gmc-dev/IISTaskで確認 (およびコードのダウンロード) できます。

于 2014-01-10T13:11:15.677 に答える
0

情報が十分ではありませんが、タスクを待っているときに機能する場合は、GC と参照に関連している可能性があると思われます。より良い方法は、ETW (EventProvider) を使用し、各要求に ActivityId を設定することです。ETW セッションを構成するだけで、すべてのメッセージをファイルにリダイレクトできます。ActivityId (Guid) をエンド ユーザーに表示できます。

于 2012-10-01T02:22:31.537 に答える
0

これをコメントとして追加して申し訳ありません。十分な担当者がいません。

https://msdn.microsoft.com/en-us/library/system.web.hosting.iregisteredobject(v=vs.110).aspx

アプリケーションは、登録された型のインスタンスを 1 つだけ持つことができます。

これは、Gervasio Marchand の受け入れられた回答が多少間違っていることを示しているようです。静的ヘルパー メソッドを呼び出すたびに、IRegisteredObject である新しい IISNotifier が作成されるためです。

于 2015-06-18T16:05:01.330 に答える