4

スレッド内のセッション状態に値を追加するいくつかの作業を実装しました。これらの値をスレッドの外で利用できるようにしたいと思います (明らかに)。

セッションに追加された情報は、セッション状態モードが「InProc」の場合、問題なくセッションの外で利用できます。

ただし、Session State モードが「StateServer」の場合は、動作が異なります。基本的に、スレッド内に設定された値は永続化される場合と永続化されない場合があります。私にはランダムに思えます。

問題を再現するコードを次に示します。

public partial class _Default : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
    }

    protected void store_Click(object sender, EventArgs e)
    {
        // Set the session values to default.
        Session["Test1"] = "No";
        Session["Test2"] = "No";

        // Set the Test1 session value in the thread.
        ThreadObject threadObject = new ThreadObject() { Username = Page.User.Identity.Name, SessionState = Session };
        worker = new Thread(new ParameterizedThreadStart(Work));
        worker.Start(threadObject);

        // Set the Test2 session value in this thread just to compare.
        Session["Test2"] = "Yes";
    }

    protected void print_Click(object sender, EventArgs e)
    {
        // Print out the Session values.
        label1.Text = string.Empty;
        label1.Text += "Inside Thread: " + Session["Test1"] + ",  \n";
        label1.Text += "Outside: " + Session["Test2"] + "\n";
    }

    private static Thread worker;

    public static void Work(object threadObject)
    {
        // Retrieve the Session object and set the Test2 value.
        ThreadObject threadObject1 = (ThreadObject)threadObject;
        HttpSessionState currentSession = threadObject1.SessionState;
        currentSession["Test1"] = "Yes";
    }
}

public class ThreadObject
{
    public string Username { get; set; }
    public HttpSessionState SessionState { get; set; }
}

上記のコードは、SessionState mode="InProc" で問題なく動作しますが、次の場合はランダムです。

<sessionState mode="StateServer"
  stateConnectionString="tcpip=localhost:42424"
  cookieless="false"
  timeout="20"/>

何か案は?

編集: したがって、以下のコメントに従って、リクエスト (メインスレッド) が終了する前にスレッドを終了する必要があります。そうしないと、セッションに追加されたものはすべて失われます。これは、メイン スレッドの最後でセッションがシリアル化され、データ ストア (アウト オブ プロセス、または SQL Server) に送信されるためです。

4

1 に答える 1

1

これはタイミングの問題だと思います。ラベルの値を設定するまでにワーカー スレッドが実行されているという保証はありません。トレッドを作成して起動するには、数MSが必要です。それまでに、メイン スレッドの残りの部分はおそらく完了しています。デバッグ出力を入れて、コードが実行される順序を確認することで、これをテストできます。

スレッド内のコードが実行されることを保証する必要がある場合 (スレッドが不要になる)、WaitOne() スレッド化メソッドを使用して、ワーカー スレッドが戻るまでメイン スレッドを待機させることができます。ただし、スレッドに設定された値に依存して並列プロセスで使用できるようにするのは危険です。

さらに、私見ですが、ASP.NET アプリではスレッドを使用しません。スレッドは少し危険だというのがコンセンサスだと思います。生成されたスレッド内の不正なコードが原因でアプリ プールがクラッシュするのを見てきました。

于 2013-02-25T05:41:34.763 に答える