Let me punch you in the face. If googling had worked for me I wouldn't have asked the question as per the forum rules.
I guess what I was actually asking is if anyone is an expert on this topic, because I have a physical simulation running on a separate thread that seems to run much slower than the same physical simulation when I programmed it in java.
Alright, so I am trying to program a multithreaded windows form right now. It's doing pretty good, except the application will randomly crash because my PictureBox control is accessed from my simulation thread. I tried wrapping its use in the thread with a lock statement but I am still getting the error. Anyone have any clue?
Alright, [I did something] but I am still getting the error. Anyone have any clue?
Context, my dear. Show your code, or at the very least an excerpt.
Here is where everything is declared and then initialized; private Flocket[] flocketArray; private flocketDisplayer displayer; private Thread simulationThread; private Object myLock;
public Form1() { InitializeComponent();
displayer = new flocketDisplayer(_display.Width, _display.Height); _display.Image = displayer.DrawFlockets(flocketArray); simulationThread = new Thread(simulateFlocking); myLock = new Object(); }
And here is where I start the thread. private void _buttonStart_Click(object sender, EventArgs e) { simulationThread.Start();
Which naturally leads us here, where the error is occurring. private void simulateFlocking() { while(true) { for (int i = 0; i < SIZE; i++) { for (int j = i + 1; j < SIZE; j++) { flocketArray[i].accelerateTowards(flocketArray[j]); flocketArray[j].accelerateTowards(flocketArray[i]); } }
for (int i = 0; i < SIZE; i++) { flocketArray[i].updateFlocket(DELTAT); }
lock (myLock) { _display.Image = displayer.DrawFlockets(flocketArray);//error is here }
} } }
Which will randomly lock up whenever it feels like it. The error I get is "InvalidOperationException", Object is currently in use elsewhere. as far as my research tells me, it is cause by accessing the System.Draw methods inside my simulation thread. Which means I must find a way to kick it out into the UI thread, but I have no idea how to do that.
You've probably already thought of this, but if not, use stackoverflow for a greater amount of people who can help. There's a much greater chance of finding an answer there than on a small forum like this.
Edit: I did a site search for your problem and someone posted this. Does that help?
Here is where everything is declared and then initialized;
[snip]
Which will randomly lock up whenever it feels like it. The error I get is "InvalidOperationException", Object is currently in use elsewhere. as far as my research tells me, it is cause by accessing the System.Draw methods inside my simulation thread. Which means I must find a way to kick it out into the UI thread, but I have no idea how to do that.
Generally, it's a bad idea to have any UI code outside of the main thread. It's not a hard and fast rule, but this design is generally considered a good rule of thumb.
I'm not super familiar with how C# does threading, but I do write threaded code on a daily basis. I only see one place where your taking the lock to protect _display. Is this correct? Because for proper threaded synchronization (in general, unless C# does something particularly strange), you need to surround the same object with the same locks everywhere you use said object.
FWIW, now that I think about it a bit more, instead of accessing _display or any other UI objects from your simulation thread, you should probably instead have some sort of data object shared between the threads. Synchronization will be a bit trickier than just a simple lock, but it'll be a cleaner design. The UI thread can poll or wait for a signal from the data object saying "I have useful data" before updating the UI.
FWIW, now that I think about it a bit more, instead of accessing _display or any other UI objects from your simulation thread, you should probably instead have some sort of data object shared between the threads. Synchronization will be a bit trickier than just a simple lock, but it'll be a cleaner design. The UI thread can poll or wait for a signal from the data object saying "I have useful data" before updating the UI.
That's what I've heard, I'll try and figure out how to do it tonight.
FWIW, now that I think about it a bit more, instead of accessing _display or any other UI objects from your simulation thread, you should probably instead have some sort of data object shared between the threads. Synchronization will be a bit trickier than just a simple lock, but it'll be a cleaner design. The UI thread can poll or wait for a signal from the data object saying "I have useful data" before updating the UI.
That's what I've heard, I'll try and figure out how to do it tonight.
Yeah... it's been a while since I did multithreaded GUI code (I mostly write server software), but based on the link Pegu posted and what I remember from my multithreaded Windows GUI programming days, Windows really hates it when you play with its GUI objects from outside the main thread.
A little tip for you is to look up events and/or condition variables and how you can use them in C#. They are similar synchronization primitives (though with slightly different uses/behaviors) that can be used to let you wait on something (i.e. data being posted to a data object) without having to constantly lock and poll said object. Here is a pseudocode example for you based on using events (which is what Windows mostly uses -- condition variables tend to be more a Unix thing):
First, somewhere in your simulation thread: simulatorFunction() { lock(lockObject) { dataObject = someData; signalEvent(dataReady); } }
Meanwhile, over in your GUI thread somewhere: waitForData() { waitOnEvent(dataReady); lock(lockObject); { myData = dataObject; }
I'm not out of the woods yet, the GUI thread is locking up without throwing an error now.
The error only seems to occur when there are no rockets on screen, so I guess that I have a problem with the displaying methods, but that's fine if I can get them to stay on screen.
Right now the flockets don't have any intelligent behaviour, but I have made them angle themselves to resist gravity's pull, which is sort of hilarious to watch as they individually start to lose fuel and begin flying around against their will.
I'm not out of the woods yet, the GUI thread is locking up without throwing an error now.
The error only seems to occur when there are no rockets on screen, so I guess that I have a problem with the displaying methods, but that's fine if I can get them to stay on screen.
Right now the flockets don't have any intelligent behaviour, but I have made them angle themselves to resist gravity's pull, which is sort of hilarious to watch as they individually start to lose fuel and begin flying around against their will.
Interesting... From what little I can gather, I agree that you're probably on the right path... Hmm... wait... are you surrounding some sort of "rockets available" variable with a lock and event? It's possible the GUI is blocking while waiting for a "rockets available" event -- hence why it only locks up when no rockets are appearing on screen.
Interesting... From what little I can gather, I agree that you're probably on the right path... Hmm... wait... are you surrounding some sort of "rockets available" variable with a lock and event? It's possible the GUI is blocking while waiting for a "rockets available" event -- hence why it only locks up when no rockets are appearing on screen.
I don't have any such method that I defined myself, but it could be possible that C#'s drawing methods are hanging up for another reason. Now that this program is sort of working, I need to take a long hard look at the choices I made programming every behavior.
The test class has the main program, which runs the program. We were told to do everything in two classes. The deck class has all the methods, and the test class has all the testing procedure in the main class.
Also, these are all separate files on my visual studio project.
Why do you have a TestHW2 class? It doesn't seem to do anything. Also, you are getting errors because you are including Deck.cpp on line 525.
Get rid of TestHW2.* It should be Deck.cpp Deck.h main.cpp -- Include Deck.h here
Your int main function should not be a member of any sort of class.
That is exactly the opposite of what I have been told in class. Also, the assignment clearly reads:
TestHW2 Class: This class drives the overall testing of the other classes.
1. Your main method resides in this class.
2. Ask the user how many hands they want to play. Validate the number they enter. If the value is less than 1 or greater than 13, print an error message and exit the program. (See the sample runs for an example of this behavior.)
3. Loop for the requested number of hands.
a. Before playing each hand, calculate the probability of drawing an ace and the probability of getting a card with a value of 10 (J, Q, K, and 10 would all be part of this count.) The probability of getting a card is the number of occurrences of that card/number of cards left to deal.
b. Deal two cards to yourself and the dealer.
c. List the hands each was dealt and calculate the total points for the hand.
d. Compare points and indicate who won.
I am using basic C++, not the Microsoft version. It's a Win32 Console Application in Visual Studio 2010.
That's silly. C++ doesn't work that way. You can rename main.cpp to TestHW2.cpp if you want and put your main function in there, but you shouldn't define it as some member function of a class.
How does your program execute then? Your main function needs to be global. Nevermind, you do have a global main. But your TestHW2 class is completely vestigial. It doesn't do anything.
Comments
If googling had worked for me I wouldn't have asked the question as per the forum rules.
I guess what I was actually asking is if anyone is an expert on this topic, because I have a physical simulation running on a separate thread that seems to run much slower than the same physical simulation when I programmed it in java.
private Flocket[] flocketArray;
private flocketDisplayer displayer;
private Thread simulationThread;
private Object myLock;
public Form1()
{
InitializeComponent();
displayer = new flocketDisplayer(_display.Width, _display.Height);
_display.Image = displayer.DrawFlockets(flocketArray);
simulationThread = new Thread(simulateFlocking);
myLock = new Object();
}
And here is where I start the thread.
private void _buttonStart_Click(object sender, EventArgs e)
{
simulationThread.Start();
_buttonAdvance.Enabled = false;
_buttonStart.Enabled = false;
_buttonStop.Enabled = true;
_buttonClear.Enabled = false;
}
Which naturally leads us here, where the error is occurring.
private void simulateFlocking()
{
while(true)
{
for (int i = 0; i < SIZE; i++)
{
for (int j = i + 1; j < SIZE; j++)
{
flocketArray[i].accelerateTowards(flocketArray[j]);
flocketArray[j].accelerateTowards(flocketArray[i]);
}
}
for (int i = 0; i < SIZE; i++)
{
flocketArray[i].updateFlocket(DELTAT);
}
lock (myLock)
{
_display.Image = displayer.DrawFlockets(flocketArray);//error is here
}
}
}
}
Which will randomly lock up whenever it feels like it.
The error I get is "InvalidOperationException", Object is currently in use elsewhere.
as far as my research tells me, it is cause by accessing the System.Draw methods inside my simulation thread. Which means I must find a way to kick it out into the UI thread, but I have no idea how to do that.
Edit: I did a site search for your problem and someone posted this. Does that help?
I'm not super familiar with how C# does threading, but I do write threaded code on a daily basis. I only see one place where your taking the lock to protect
_display
. Is this correct? Because for proper threaded synchronization (in general, unless C# does something particularly strange), you need to surround the same object with the same locks everywhere you use said object._display
or any other UI objects from your simulation thread, you should probably instead have some sort of data object shared between the threads. Synchronization will be a bit trickier than just a simple lock, but it'll be a cleaner design. The UI thread can poll or wait for a signal from the data object saying "I have useful data" before updating the UI.https://en.wikipedia.org/wiki/Dining_philosophers_problem
A little tip for you is to look up events and/or condition variables and how you can use them in C#. They are similar synchronization primitives (though with slightly different uses/behaviors) that can be used to let you wait on something (i.e. data being posted to a data object) without having to constantly lock and poll said object. Here is a pseudocode example for you based on using events (which is what Windows mostly uses -- condition variables tend to be more a Unix thing):
First, somewhere in your simulation thread:
simulatorFunction()
{
lock(lockObject)
{
dataObject = someData;
signalEvent(dataReady);
}
}
Meanwhile, over in your GUI thread somewhere:
waitForData()
{
waitOnEvent(dataReady);
lock(lockObject);
{
myData = dataObject;
}
// Do what you need to do with myData
}
Now to find a less retarded motion equation.
Right now the flockets don't have any intelligent behaviour, but I have made them angle themselves to resist gravity's pull, which is sort of hilarious to watch as they individually start to lose fuel and begin flying around against their will.
I am getting a slew of errors I don't even understand yet. I just started C++, we haven't even done pointers yet. My errors are this, basically: Anyone want to assist? I am currently not near anyone with C++ knowledge...
Get rid of TestHW2.* It should be
Deck.cpp
Deck.h
main.cpp -- Include Deck.h here
Your int main function should not be a member of any sort of class.
Also, these are all separate files on my visual studio project.
Nevermind, you do have a global main. But your TestHW2 class is completely vestigial. It doesn't do anything.