web-dev-qa-db-ja.com

異なるスレッドからHttpContext.Currentにアクセスする

SiteCrawler.csと呼ばれるクラスでいくつかのメソッドを実行する約25の異なるスレッドを開始するC#ASP.NETアプリケーションがあります。

HttpContext.Current.Sessionユーザーが行った検索の結果を保存し、すべてのスレッドの実行が終了したときにユーザーに提示したい。私の問題は、HttpContext.Currentオブジェクトは存在しないため、生成されたスレッドではnullです。

アプリケーションがマルチスレッド化されている場合の制限のため、セッションを使用せずにユーザー/セッション固有のデータを保存するには、他にどのようなオプションが必要ですか?

Stackoverflowのあらゆる領域を検索して解決策を見つけようとしましたが、運はありませんでした。

51
Raydk

私のアプリケーションには_HttpContext.Current_を使用するコードがたくさんあり、そのコードを変更することはできません。

以下のサンプルのworker.DoWork()は、そのコードを使用しています。そして、別のスレッドで実行する必要がありました。

私は次の解決策に来ました:

_ HttpContext ctx = HttpContext.Current;
 Thread t = new Thread(new ThreadStart(() =>
                {
                    HttpContext.Current = ctx;
                    worker.DoWork();
                }));
 t.Start();
 // [... do other job ...]
 t.Join();
_
71

Fritz Onionによるこの記事をご覧ください。 サーバーサイドWebコードでのスレッドの使用と非同期ハンドラーの構築 。かなり長いですが、あなたの要件はささいなことではありません。

また、K。スコットアレンは、この問題についてやや短い記事を投稿しました: Working With HttpContext.Current

11
Dennis Traub

@Roryは上記のコメントを作成しました。HttpContextの特定のオブジェクトは、スレッドに渡してもnullになります。これはUserプロパティで起こりました。そのため、代わりに次のようにUserをスレッドCurrentPrincipalにコピーできます。

コントローラーコンテキストで、ユーザーを保存します。

            _user = HttpContext.Current.User;
            var processThread = new Thread(() => ThreadedCode());
            processThread.Start();

スレッドで、「スレッド」ユーザーを設定します。

    private static void ThreadedCode()
    {
        // Workaround for HttpContext.Current.User being null.
        // Needed for CreatedBy and RevisedBy.
        Thread.CurrentPrincipal = _user;

HttpContextは、リクエストの有効期間中のみ利用できることに注意してください。スレッドはリクエストよりも潜在的にはるかに長く存続するため、そもそもスレッドが必要です。 :)

7
Jess

HttpContext.CurrentをクラスSiteCrawler.csのコンストラクターに追加するだけです

public class SiteCrawler
{
     HttpContext context = HttpContext.Current;

    public void Method()
    {
        context.WhateverYouWant
    }
}
4
jjspierx

データベースに保存してから、ユーザーのブラウザに更新を続けるか、ajaxを使用させるか、新しいシグナルを使用して、結果が既にdbに書き込まれているかどうかを確認できます。それが役に立てば幸い。

3
ysrb