2014-05-25 3 views
0

내 서버 클래스가 필요한 모든 정보를받은 후 새 양식을 작성해야하는 이벤트가 발생합니다. 이 양식의 버튼을 클릭하면 ThreadStateException이 표시됩니다. 나는 alawys가 주 스레드 내에서 양식을 열어야한다는 것을 알고 있습니다.하지만 이벤트가 볼 롤링을 설정하면 양식이 다른 스레드에서 작성됩니다. MVC 패턴을 구현합니다. 내 주요 방법은 [STAThread] 주석을 가지고 있습니다.다른 스레드가 만든 양식의 STAThread 오류

내 서버는 출발점이 될 것입니다 :

private void HandleClient(TcpClient client) 
{ 
    PACKET_ID packetID = ServerHelper.ReadPacketID(client); 

    switch (packetID) 
    {  
     case PACKET_ID.START_GAME: // start a new game => create a new Form 
      onGameStarted(); // fire event 
      break; 

현재 눈에 보이는 형태는 "onGameStarted"이벤트를 등록하고이 방법을 호출합니다

나는 MVC 패턴을 구현하고있다으로
private void StartGame() 
{ 
    Invoke((MethodInvoker)delegate() { Hide(); }); 
    controller.StartGame(); // call controller to replace model and view 
    Close(); 
} 

, 컨트롤러를 뷰에 의해 호출됩니다.

public void StartGame() 
{ 
    GameModel gameModel = new GameModel(model.PlayerData); // new model ("model" is the old model) 
    GameView gameView = new GameView(model.PlayerData); // new view (which needs to be run in a STAThread 
    SetViewModel(gameView, gameModel); 
    gameView.ShowDialog(); // show new form 
} 

public void SetViewModel(IView<GameModel> view, GameModel model) 
{ 
    // set/replace new view and model 
    this.viewGame = view; 
    this.model = model; 
    // add controller 
    this.viewGame.AddController(this); 
    this.viewGame.SubscribeEvents(model); 
    viewGame.InitGUI(); 
} 

이 메소드는 마지막으로 예외

public partial class GameView : Form, IView<GameModel> 
{ 
    //... 
    private void buLoadMap_Click(object sender, EventArgs e) 
    { 

     OpenFileDialog objDialog = new OpenFileDialog(); 
     objDialog.Filter = "txt files (*.txt)|*.txt|All files (*.*)|*.*"; 
     if (objDialog.ShowDialog() == DialogResult.OK) // ThreadStateException 
     { 
      laError.Text = "Selected Map: " + objDialog.FileName; 
      controller.LoadOwnMap(objDialog.FileName); 

     } 
     buLoadMap.Enabled = false; 
    } 

아무도 예외가 throw되지 않도록 코드를 변경하는 방법을 말해 줄 수 있습니까? 감사합니다.

답변

1

방금 ​​해결책이 있습니다. 이 게시물을 삭제하지 않고 내 솔루션을 게시하기로 결정했습니다.

은 내가 이벤트를 onGameStarted 다음 주 스레드를 호출 구독 형태의 InvokeRequired 속성을 확인. StartGame() 메소드를 약간 변경했습니다.

private void StartGame() 
{ 
    if (this.InvokeRequired) 
    { 
     Action invoke = new Action(StartGame); 
     this.Invoke(invoke); 
    } 
    else 
    { 
     Hide(); 
     controller.StartGame(); 
     Close(); 
    } 
}