2013-02-25 7 views
4

스레드 내에서 세션 상태에 값을 추가하는 작업을 구현했습니다. 이 값을 스레드 외부에서 사용할 수있게하고 싶습니다 (분명히).세션 모드 "ServerState"가 스레드에서 세션을 제대로 처리하지 않습니다.

세션에 추가 된 정보는 세션 상태 모드가 "InProc"일 때 아무런 문제없이 세션 외부에서 사용할 수 있습니다.

그러나 세션 상태 모드가 "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의 모드 = "에서 InProc"함께 잘 작동하지만 무작위입니다 :

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

어떤 아이디어?

EDIT : 아래의 설명에 따라 요청 (주 스레드)이 완료되기 전에 스레드가 완료되어야합니다. 그렇지 않으면 세션에 추가 된 모든 항목이 손실됩니다. 이것은 주 스레드의 끝에 세션이 직렬화되어 데이터 저장소 (Out of Process 또는 SQL Server)로 전송되기 때문입니다.

답변

1

타이밍 문제라고 생각합니다. 레이블 값을 설정할 때까지 작업자 스레드가 실행되지 않을 수도 있습니다. 트레드를 만들고 발사하는데 MS가 필요합니다. 그때까지, 당신의 메인 스레드의 나머지 부분은 아마 완료되었습니다. 디버그 출력을 넣고 코드가 실행되는 순서를 확인하여이를 테스트 할 수 있습니다.

스레드의 코드가 실행되도록 보장해야한다면 (스레드가 필요하지 않음) WaitOne() 스레딩 메서드를 사용하여 주 스레드가 작업자 스레드가 돌아올 때까지 기다릴 수 있습니다. 그러나 병렬 프로세스에서 사용할 수있는 스레드의 값 설정에 따라 위험합니다.

또한 IMHO, 나는 ASP.NET 응용 프로그램에서 스레드를 사용하지 않을 것입니다. 나는 그들이 약간 위험하다고 생각합니다. 스폰 된 스레드 내부의 잘못된 코드로 인해 앱 풀 크래시가 발생했습니다.

+0

저는 여러분이 _race condition_에 맞다고 생각하지만 스레딩은 ASP.NET에서도 중요 할 수 있습니다. 제대로 구현되고 사용된다면 악의는 없습니다. ASP.NET Main-Thread가 무엇이든 대기하게하면 스레드가 다른 요청을 처리 할 수있게됩니다. MVC가 Task 를 허용하는 이유입니다. – TGlatzer

+0

동의하지 않을 수 있습니다. "올바르게 구현 된 경우"는 일반적인 문제인 것처럼 보입니다 .-) – Ripside

+0

안녕하세요, 라벨 설정 코드는 버튼 클릭의 일부로, 몇 초 전에 기다렸습니다. 세션 값을 레이블에 인쇄하려고합니다. 타이밍 문제라고 확신 할 수 없습니다. print_Click 버튼을 반복해서 누르면 스레드가 세션에 값을 설정할 수있게됩니다. – Ivan