Ошибка STAThread в форме, созданной другим потоком

После того, как мой серверный класс получил всю необходимую информацию, он запускает событие, которое должно создать новую форму. При нажатии кнопки в этой форме я получаю ThreadStateException. Я знаю, что в любом случае должен открыть форму в основном потоке, но поскольку событие запускает процесс, форма создается в другом потоке. Я реализую шаблон MVC. Мой основной метод имеет аннотацию [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 и вызывает этот метод:

private void StartGame()
{
    Invoke((MethodInvoker)delegate() { Hide(); });
    controller.StartGame(); // call controller to replace model and view
    Close();
}

Когда я реализую шаблон MVC, контроллер вызывается представлением:

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;
    }

Может ли кто-нибудь сказать мне, как изменить код, чтобы не выбрасывалось исключение? Спасибо!


person null    schedule 25.05.2014    source источник


Ответы (1)


Я только что получил решение. Я решил не удалять этот пост, а опубликовать свое решение.

Я проверил атрибут InvokeRequired формы, которая подписывается на событие onGameStarted, а затем вызвал основной поток. Я немного изменил метод StartGame():

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