2013-02-25 4 views
4

Я реализовал некоторую работу, которая добавляет значения в состояние Session внутри Thread. Я бы хотел, чтобы эти значения были доступны вне Thread (очевидно).Режим сеанса «ServerState» не обрабатывает сеанс в потоке должным образом

Информация, добавленная в Сессию, доступна вне сеанса без каких-либо проблем, когда режим состояния сеанса - «InProc».

Однако, когда режим состояния сеанса имеет значение «StateServer», поведение отличается. В основном значения, установленные внутри Thread, сохраняются иногда, а иногда и не. Мне кажется случайным.

Вот код, который воспроизводит проблему.

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 = "InProc", но случайна:

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

Любые идеи?

РЕДАКТИРОВАТЬ: В соответствии с комментариями ниже поток должен завершиться до завершения запроса (основной темы), в противном случае все, что добавлено в сеанс, будет потеряно. Это связано с тем, что в конце основного потока сеанс сериализуется и отправляется в хранилище данных (Out of Process или SQL Server).

ответ

1

Я думаю, что это временная проблема - нет гарантии, что ваш рабочий поток будет выполнен к моменту установки значений вашего ярлыка. Для создания и запуска протектора требуется несколько MS. К тому времени остальная часть вашего основного потока, вероятно, завершилась. Вы можете проверить это, поставив вывод отладки и посмотреть порядок выполнения вашего кода.

Если вам необходимо гарантировать выполнение кода в потоке (что исключает необходимость в потоке), вы можете использовать метод потоковой обработки WaitOne(), чтобы ваш основной поток ожидал возврата рабочего потока. Но в зависимости от значения, установленного в потоке, доступном в параллельном процессе, является рискованным.

Дополнительно - IMHO, я бы не использовал потоки в приложениях ASP.NET. Я считаю, что консенсус в том, что они немного опасны. Я видел, как сбой в пуле приложений из-за плохого кода внутри порожденного потока.

+0

Я думаю, что вы правы с условием _race, но потоки могут быть важны и для ASP.NET. Нет ничего злого, если оно реализовано и используется правильно. Предотвращение ожидания Main-Thread ASP.NET на чем-либо сделает поток доступным для обработки других запросов. Именно поэтому MVC позволяет Task . – TGlatzer

+0

Я не могу не согласиться - даже если ваше предостережение - «если выполнено правильно», похоже, является общей проблемой :-) – Ripside

+0

Эй, ну, код установки ярлыка является частью нажатия кнопки, и я подождал больше, чем за несколько секунд до пытаясь распечатать значения сеанса в метке. Так что я не уверен, что это вопрос времени. Повторное нажатие кнопки print_Click должно в конечном итоге разрешить Thread установить его значение в сеанс. – Ivan