Reputation: 1443
After my server class received all necessary information, it fires an event that is supposed to create a new Form. When clicking on a button on this form, I get an ThreadStateException. I know that I should alawys open a form within the main thread., but as an event sets the ball rolling, the form is created in another thread. I implement the MVC pattern. My main method does have the [STAThread] annotation.
My Server is the starting point:
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;
The currently visible form subscribed the "onGameStarted" event and invokes this method:
private void StartGame()
{
Invoke((MethodInvoker)delegate() { Hide(); });
controller.StartGame(); // call controller to replace model and view
Close();
}
As I am implementing the MVC pattern, the controller is then called by the view:
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();
}
This method finally throws the exception
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;
}
Can anyone tell me how to change the code, so that no exception is thrown? Thanks!
Upvotes: 0
Views: 207
Reputation: 1443
I just got the solution. I decided not to delete this post but to publish my solution.
I checked the InvokeRequired attribute of the form that subscribes to the onGameStarted event and then invoked the main thread. I slightly changed the StartGame() method:
private void StartGame()
{
if (this.InvokeRequired)
{
Action invoke = new Action(StartGame);
this.Invoke(invoke);
}
else
{
Hide();
controller.StartGame();
Close();
}
}
Upvotes: 1