ここに問題があります。私のWebアプリには、時間のかかるタスクのために別のスレッドを開始するページがあります。この新しいスレッドでは、アーキテクチャメソッドの1つ(別のプロジェクト内-アーキテクチャプロジェクト)を呼び出しています。問題は次のとおりです。このメソッドの1つで、HttpContext.Current.Sessionフィールドにアクセスします。しかし、アプリケーションを起動すると、このオブジェクト(HttpContext.Current.Session)にnull参照があるという例外がスローされます。HttpContext.Current.Sessionにアクセスするために、新しいスレッドのコンテキストをHttpApplicationコンテキストと同じに設定するにはどうすればよいですか?
3 に答える
ここで考慮すべきことがいくつかあります。
スレッドの存続期間がページの存続期間と等しく、へのランダムアクセスが大量に必要な場合は、静的プロパティHttpSessionState
を使用してバックグラウンドスレッドを作成する呼び出しからを取得する必要があります。SynchronizationContext
Current
それを取得したら、それをスレッドに渡すことができます。リクエストに関連付けられているもの(これにはセッションも含まれます)にアクセスする必要がある場合は、スレッドに渡したメソッドを呼び出して値を取得できます。 (またはそれらを設定する):HttpContextBase
Post
SynchronizationContext
// From thread servicing request.
var sc = SynchronizationContext.Current;
// Run the task
Task t = Task.Run(() => {
// Do other stuff.
// ...
// The value to get from the session.
string sessionValue = null;
// Need to get something from the session?
sc.Post(() => {
// Get the value.
sessionValue = HttpContext.Current.Session["sessionValue"];
}
// Do other stuff.
// ...
});
HttpContextBase
(およびそれに関連するもの)へのアクセスはスレッドセーフではなく、要求を処理するスレッド(まあ、コンテキスト)に関連付けられているため、これを行うことが重要です。
Post
メソッドはブロックしないため、の呼び出しの後に来るコードPost
(つまり、後の行// Do other stuff.
)は、に渡されるデリゲートから独立している必要があることに注意してくださいPost
。後に続くコードが依存していて、続行する前に呼び出しが完了するのを待つ必要がある場合は、Send
メソッドを呼び出すことができます。同じ署名があり、デリゲート内のコードが実行されるまでブロックされます。
とはいえ、値への読み取り専用アクセスのみが必要な場合は、コードを呼び出す前に値を取得してから、バックグラウンドスレッドで値にアクセスすることをお勧めします。
// Get the values needed in the background thread here.
var values = {
SessionValue = HttpContext.Current.Session["sessionValue"];
};
// Run the task
Task t = Task.Run(() => {
// Do other stuff.
// ...
// Work with the session value.
if (values.SessionValue == ...)
// Do other stuff.
// ...
});
リクエストが処理された後もスレッドが処理を続行する場合は、読み取り専用状態のみであり、スレッドを開始する前にそれをキャプチャする必要があります。リクエストが処理されると、セッションが存続していても、それは論理的な概念です。セッション状態のプロバイダー(セッション状態マネージャー、SQL Serverなど)によっては、新しい要求が着信するたびにオブジェクトがハイドレイトされる可能性があります。
また、セッションタイムアウトの問題にも対処する必要があり、アクセスしたいポイントにセッションが存在するかどうかさえわかりません。