PeterT
PeterT

Reputation: 289

C# MultiThreading is causing unhandled exception of type 'System.OutOfMemoryException'

(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

Answers (2)

radianz
radianz

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

Peter Morris
Peter Morris

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

Related Questions