Reputation: 289
(Background) I am creating a stock market emulation program to further my C# knowledge. I previously created this program in Java.
(Issue) In Java, I was able to create a new thread in order to have it loop and update my GUI's labels every x amount of time. I researched methods to do this in C# and came across the timer, this didn't work for me and so I resorted to multi-threading.
Upon startup of the form I create a new thread
/// <summary>
/// stock emulation startup
/// </summary>
public stockEmu()
{
CheckForIllegalCrossThreadCalls = false; //if this is true, then cross-thread changes cannot be made (repeater cannot set labels if true)
initializeValues(); //this will set the startup values e.g stock prices and user money
ThreadStart loopThread = new ThreadStart( repeater ); //opens a new thread
Thread openThread = new Thread( loopThread ); //opens a new thread
openThread.Start(); //opens a new thread
InitializeComponent(); //initializes the form
this.updateLabels(); //needs to be after initializecomponent or null exception is thrown (because the labels are not drawn yet)
}
Here is the new thread method:
/// <summary>
/// infinite loop to execute every x seconds (using a new thread)
/// repeater uses cross-thread operation(s) and so CheckForIllegalCrossThreadCalls has been set to false
/// MSDN recommends against this, it is executed safely however
/// </summary>
private void repeater()
{
while( true )
{
Thread.Sleep( 5000 ); //sleep (pause) the thread for 5 seconds
instance = instance + 1; //add to the current instance (this is used to display what "day" we're on
changePrices(); //change the prices of the stocks
updateLabels(); //update the form's labels to display the new values
}
}
Here are the methods the repeater calls every 5 seconds
/// <summary>
/// this will change the prices every x seconds based on current prices etc
/// </summary>
private void changePrices()
{
marketController mC = new marketController();
for( int i = 0 ; i < stocks.Length ; i++ )
{
mC.changePrices( stocks [ i ] , i ); //mc for marketController, object reference, change prices will calc the price changes
}
return;
}
mC.changePrices doesn't actually do anything yet, but it does not get stuck there.
/// <summary>
/// method used to update all display labels every x seconds (based on repeater)
/// </summary>
public void updateLabels()
{
try
{
this.userMoneyLabel.Text = "Your money: " + this.getUserMoney().ToString(); //changes the user's money label
this.currentDayLabel.Text = "Day: " + this.getInstance().ToString(); //changes the day label
this.setStocksCombined(); //sets the array of combined stock prices and stock names
this.stockListBox.Items.Clear(); //clear the list box because it will constantly stack the items
this.stockListBox.Items.AddRange( stocksCombined ); //adds the combined array to the list box (stocks + stockNames)
}
catch( Exception e )
{
MessageBox.Show( "Error: " + e );
}
}
All of the relevant labels update fine, this problem also persisted before I added setStocksCombined() and so I don't believe the problem lies there.
This is the error that is thrown:
An unhandled exception of type 'System.OutOfMemoryException' occurred in mscorlib.dll
I haven't opened any additional threads apart from repeater, the repeater normally throws this error when it reached instance 7.
Thanks in advance (hopefully)
Edit:
Thanks to @RichardSzalay and @MichaelThePotato I have implemented a timer using this example: https://stackoverflow.com/a/12535833/6639187
Upvotes: 0
Views: 780
Reputation: 71
You can also use the free tool ClrDbg to inspect the heap of your .Net application and find the cause of the memory issue https://sourceforge.net/projects/clrdbg/
Upvotes: 0
Reputation: 23284
One of the methods you use but have not listed is likely to be holding on to references. Use a memory profiler to find out where your app is leaking RedGate does a 14 day free trial.
If your app is not leaking then it is simply trying to load in too much data in one go.
Upvotes: 2