How to stop a simulation while running
-
Luc, Thanks for your answer! I'm trying to use a backgroundworker, but I'm having some trouble with getting it to work. I followed the example on MSDN, and first put:
System::ComponentModel::BackgroundWorker^ worker
in the code. Then I try to initialize the worker by:worker->DoWork += gcnew DoWorkEventHandler(this, &form::worker_doWork);
But now I get an error on this last line while running the program: "Object reference not set to an instance of an object". Any idea what the problem could be? ATJAI guess you'd get that if you don't have executed a
worker=gcnew BackgroundWorker
somewhere before. :)Luc Pattyn [Forum Guidelines] [Why QA sucks] [My Articles] Nil Volentibus Arduum
Please use < PRE > tags for code snippets, it preserves indentation, and improves readability.
-
I guess you'd get that if you don't have executed a
worker=gcnew BackgroundWorker
somewhere before. :)Luc Pattyn [Forum Guidelines] [Why QA sucks] [My Articles] Nil Volentibus Arduum
Please use < PRE > tags for code snippets, it preserves indentation, and improves readability.
Thanks, it works now! However, there is one very strange thing. When I compile the code everything works, but in debug mode nothing happens if I click the button that triggers the backgroundworker events. Any idea what this problem could be?
-
Thanks, it works now! However, there is one very strange thing. When I compile the code everything works, but in debug mode nothing happens if I click the button that triggers the backgroundworker events. Any idea what this problem could be?
Arjen Tjallema wrote:
Any idea what this problem could be?
without seeing the relevant code, no. :)
Luc Pattyn [Forum Guidelines] [Why QA sucks] [My Articles] Nil Volentibus Arduum
Please use < PRE > tags for code snippets, it preserves indentation, and improves readability.
-
Arjen Tjallema wrote:
Any idea what this problem could be?
without seeing the relevant code, no. :)
Luc Pattyn [Forum Guidelines] [Why QA sucks] [My Articles] Nil Volentibus Arduum
Please use < PRE > tags for code snippets, it preserves indentation, and improves readability.
That makes sense... Here is the relevant part of my code. I made a BackgroundWorker called simWorker, and a start and stop button which should, obviously, start and stop my simulation. Starting it works fine when I compile the code, but nothing happens when I run in debug mode. The stop button is not working yet, I'm still finding out how to deal with that. Hope you can think of something to make this also run in debug mode, that would make life much easier. Thanks!
namespace uDP2 {
public ref class DPSim : public System::Windows::Forms::Form
{
static clModel^ model = gcnew clModel;
public:
DPSim(clModel^ mdl)
{
InitializeComponent();
model = mdl;
InitializeSimWorker();
}protected: ~DPSim() { if (components) { delete components; } } private: System::ComponentModel::IContainer^ components; protected: private: System::ComponentModel::BackgroundWorker^ simWorker; void InitializeSimWorker(){ simWorker = gcnew BackgroundWorker; simWorker->DoWork += gcnew DoWorkEventHandler( this, &DPSim::simWorker\_DoWork ); } void simWorker\_DoWork( Object^ sender, DoWorkEventArgs^ e ){ BackgroundWorker^ worker = dynamic\_cast<BackgroundWorker^>(sender); e->Result = simulate(model, worker, e); }
#pragma region Windows Form Designer generated code
{
// code to generate form and components
}
#pragma endregion
private: clModel^ simulate(clModel^ model, BackgroundWorker^ worker, DoWorkEventArgs^ e){
// run simulation
return model;
}
private: System::Void butStart_Click(System::Object^ sender, System::EventArgs^ e) {
simWorker->RunWorkerAsync(model);
}
private: System::Void butStop_Click(System::Object^ sender, System::EventArgs^ e) {
model->state->modelRunning = Convert::ToInt32(0);
}
};
} -
That makes sense... Here is the relevant part of my code. I made a BackgroundWorker called simWorker, and a start and stop button which should, obviously, start and stop my simulation. Starting it works fine when I compile the code, but nothing happens when I run in debug mode. The stop button is not working yet, I'm still finding out how to deal with that. Hope you can think of something to make this also run in debug mode, that would make life much easier. Thanks!
namespace uDP2 {
public ref class DPSim : public System::Windows::Forms::Form
{
static clModel^ model = gcnew clModel;
public:
DPSim(clModel^ mdl)
{
InitializeComponent();
model = mdl;
InitializeSimWorker();
}protected: ~DPSim() { if (components) { delete components; } } private: System::ComponentModel::IContainer^ components; protected: private: System::ComponentModel::BackgroundWorker^ simWorker; void InitializeSimWorker(){ simWorker = gcnew BackgroundWorker; simWorker->DoWork += gcnew DoWorkEventHandler( this, &DPSim::simWorker\_DoWork ); } void simWorker\_DoWork( Object^ sender, DoWorkEventArgs^ e ){ BackgroundWorker^ worker = dynamic\_cast<BackgroundWorker^>(sender); e->Result = simulate(model, worker, e); }
#pragma region Windows Form Designer generated code
{
// code to generate form and components
}
#pragma endregion
private: clModel^ simulate(clModel^ model, BackgroundWorker^ worker, DoWorkEventArgs^ e){
// run simulation
return model;
}
private: System::Void butStart_Click(System::Object^ sender, System::EventArgs^ e) {
simWorker->RunWorkerAsync(model);
}
private: System::Void butStop_Click(System::Object^ sender, System::EventArgs^ e) {
model->state->modelRunning = Convert::ToInt32(0);
}
};
}Hi, that code is not really OK. I do not know what is the exact cause of your symptoms, however I'll offer some comments that should bring you closer to success: 1. I would defer all initialization of the simulator till the start button is pressed. You don't need a BGW if no simulation is ordered. 2. I would then also disable the start button (and enable the stop button) for as long as the simulator is running. 3. a BGW needs more initialization; have a look at one of the examples, e.g. here[^]. You probably want to include (this is C#, change syntax as required):
bw.WorkerSupportsCancellation = true;
bw.WorkerReportsProgress = true;
bw.DoWork += new DoWorkEventHandler(bw_DoWork);
bw.ProgressChanged += new ProgressChangedEventHandler(bw_ProgressChanged);
bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);4. You should provide a RunWorkerCompleted handler; that is where the results become available, the exceptions of DoWork are available (through e->Error), and the start button could be re-enabled (and the stop button disabled again). 5. You could use the built-in BGW cancellation mechanism, although having your own could probably be equally good. 6. FYI: other threads are not allowed to touch GUI parts, however both the ProgressChanged and RunWorkerCompleted handlers run on the main thread (assuming you created the BGW on the main thread), and so are allowed to modify the GUI. Your model might take advantage of that. 7. a BGW uses a ThreadPool thread, i.e. its thread gets recycled automatically, you don't need to worry about that. Use a new BGW each time! Maybe (your symptom description was a bit cryptic here) together with (1) above, that is what caused your discomfort in compiling/running/debugging. :)
Luc Pattyn [Forum Guidelines] [Why QA sucks] [My Articles] Nil Volentibus Arduum
Please use < PRE > tags for code snippets, it preserves indentation, and improves readability.
-
Hi, that code is not really OK. I do not know what is the exact cause of your symptoms, however I'll offer some comments that should bring you closer to success: 1. I would defer all initialization of the simulator till the start button is pressed. You don't need a BGW if no simulation is ordered. 2. I would then also disable the start button (and enable the stop button) for as long as the simulator is running. 3. a BGW needs more initialization; have a look at one of the examples, e.g. here[^]. You probably want to include (this is C#, change syntax as required):
bw.WorkerSupportsCancellation = true;
bw.WorkerReportsProgress = true;
bw.DoWork += new DoWorkEventHandler(bw_DoWork);
bw.ProgressChanged += new ProgressChangedEventHandler(bw_ProgressChanged);
bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);4. You should provide a RunWorkerCompleted handler; that is where the results become available, the exceptions of DoWork are available (through e->Error), and the start button could be re-enabled (and the stop button disabled again). 5. You could use the built-in BGW cancellation mechanism, although having your own could probably be equally good. 6. FYI: other threads are not allowed to touch GUI parts, however both the ProgressChanged and RunWorkerCompleted handlers run on the main thread (assuming you created the BGW on the main thread), and so are allowed to modify the GUI. Your model might take advantage of that. 7. a BGW uses a ThreadPool thread, i.e. its thread gets recycled automatically, you don't need to worry about that. Use a new BGW each time! Maybe (your symptom description was a bit cryptic here) together with (1) above, that is what caused your discomfort in compiling/running/debugging. :)
Luc Pattyn [Forum Guidelines] [Why QA sucks] [My Articles] Nil Volentibus Arduum
Please use < PRE > tags for code snippets, it preserves indentation, and improves readability.
Thanks a lot for your comments! I've used them in my code, but the problem with debugging is still not solved. My start button contains the following code:
simWorker = gcnew BackgroundWorker;
simWorker->WorkerSupportsCancellation = true;
simWorker->WorkerReportsProgress = true;
simWorker->DoWork += gcnew DoWorkEventHandler(this, &uDP2::DPSim::simWorker_DoWork);
simWorker->ProgressChanged += gcnew ProgressChangedEventHandler(this, &uDP2::DPSim::simWorker_ProgressChanged);
simWorker->RunWorkerCompleted += gcnew RunWorkerCompletedEventHandler(this, &uDP2::DPSim::simWorker_RunWorkerCompleted);
butReset->Enabled = false;
butPause->Enabled = true;
butStart->Enabled = false;
simWorker->RunWorkerAsync(model);When I compile and run the program this works fine, the last line in this code runs the actual model. However, when I step through the code in debug mode the last line seems to be skipped; it passes this line without running the model. I don't have a clue what's going on here, this seems to be very strange to me... Update: It seems that the code which updates the data on my Graphical User Interface in each timestep causes the problem. I have an "updateGUI" function which is called in each timestep from the simulation, which is again called by RunWorkerAsync. The updateGUI function contains:
lblTime->Text = Convert::ToString(Math::Round(\*model->state->t,2)); txtX->Text = Convert::ToString(Math::Round(model->state->eta\[0,0\],2)); txtY->Text = Convert::ToString(Math::Round(model->state->eta\[1,0\],2)); txtPsi->Text = Convert::ToString(Math::Round(model->state->eta\[5,0\],2)); lblWindDirSim->Text = Convert::ToString(\*model->environment->windDir / Math::PI \* 180);
If I comment this out the code runs fine in debug mode, otherwise it doesn't. Any idea what the problem could be?
modified on Thursday, June 24, 2010 5:41 AM
-
Thanks a lot for your comments! I've used them in my code, but the problem with debugging is still not solved. My start button contains the following code:
simWorker = gcnew BackgroundWorker;
simWorker->WorkerSupportsCancellation = true;
simWorker->WorkerReportsProgress = true;
simWorker->DoWork += gcnew DoWorkEventHandler(this, &uDP2::DPSim::simWorker_DoWork);
simWorker->ProgressChanged += gcnew ProgressChangedEventHandler(this, &uDP2::DPSim::simWorker_ProgressChanged);
simWorker->RunWorkerCompleted += gcnew RunWorkerCompletedEventHandler(this, &uDP2::DPSim::simWorker_RunWorkerCompleted);
butReset->Enabled = false;
butPause->Enabled = true;
butStart->Enabled = false;
simWorker->RunWorkerAsync(model);When I compile and run the program this works fine, the last line in this code runs the actual model. However, when I step through the code in debug mode the last line seems to be skipped; it passes this line without running the model. I don't have a clue what's going on here, this seems to be very strange to me... Update: It seems that the code which updates the data on my Graphical User Interface in each timestep causes the problem. I have an "updateGUI" function which is called in each timestep from the simulation, which is again called by RunWorkerAsync. The updateGUI function contains:
lblTime->Text = Convert::ToString(Math::Round(\*model->state->t,2)); txtX->Text = Convert::ToString(Math::Round(model->state->eta\[0,0\],2)); txtY->Text = Convert::ToString(Math::Round(model->state->eta\[1,0\],2)); txtPsi->Text = Convert::ToString(Math::Round(model->state->eta\[5,0\],2)); lblWindDirSim->Text = Convert::ToString(\*model->environment->windDir / Math::PI \* 180);
If I comment this out the code runs fine in debug mode, otherwise it doesn't. Any idea what the problem could be?
modified on Thursday, June 24, 2010 5:41 AM
I see two possibilities: 1. you did not follow my earlier point #6, so the offending code is in DoWork, rather than in the ProgressChanged handler. 2. that code is throwing an exception; put it all in a try-catch and look at Exception.ToString(). BTW: your RunWorkerCompleted should check e.Error, which would contain any uncaught exception that has occured while the BGW was running. :)
Luc Pattyn [Forum Guidelines] [Why QA sucks] [My Articles] Nil Volentibus Arduum
Please use < PRE > tags for code snippets, it preserves indentation, and improves readability.
-
I see two possibilities: 1. you did not follow my earlier point #6, so the offending code is in DoWork, rather than in the ProgressChanged handler. 2. that code is throwing an exception; put it all in a try-catch and look at Exception.ToString(). BTW: your RunWorkerCompleted should check e.Error, which would contain any uncaught exception that has occured while the BGW was running. :)
Luc Pattyn [Forum Guidelines] [Why QA sucks] [My Articles] Nil Volentibus Arduum
Please use < PRE > tags for code snippets, it preserves indentation, and improves readability.
Luc, I found out I did indeed not follow your point #6, I guess I didn't completely understand. Now it works fine, thanks a lot for all your quick and useful help!! Regards, ATJA
-
Luc, I found out I did indeed not follow your point #6, I guess I didn't completely understand. Now it works fine, thanks a lot for all your quick and useful help!! Regards, ATJA
You're welcome. You may want to read this[^] to know more about GUI and threads. :)
Luc Pattyn [Forum Guidelines] [Why QA sucks] [My Articles] Nil Volentibus Arduum
Please use < PRE > tags for code snippets, it preserves indentation, and improves readability.
-
You're welcome. You may want to read this[^] to know more about GUI and threads. :)
Luc Pattyn [Forum Guidelines] [Why QA sucks] [My Articles] Nil Volentibus Arduum
Please use < PRE > tags for code snippets, it preserves indentation, and improves readability.
That indeed looks interesting for what I'm doing, I'll have a look at it. Thanks again!