在我的服务器类收到所有必要信息后,它会触发一个应该创建新表单的事件。单击此表单上的按钮时,我得到 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" event并调用此方法:
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;
}
有谁能告诉我如何更改代码,以便不抛出任何异常? 谢谢!
答案 0 :(得分:1)
我刚刚得到了解决方案。我决定不删除这篇文章,而是发布我的解决方案。
我检查了订阅 onGameStarted 事件的表单的 InvokeRequired 属性,然后调用了主线程。我略微改变了StartGame()方法:
private void StartGame()
{
if (this.InvokeRequired)
{
Action invoke = new Action(StartGame);
this.Invoke(invoke);
}
else
{
Hide();
controller.StartGame();
Close();
}
}