0

(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

13
  • MSDN recommends against this, it is executed safely however seems like a weird assumption given that the application crashes. Not saying it is causing it but it might be. Commented Jul 26, 2016 at 10:37
  • You should really look into using Task to do your background work. Creating threads directly in .net in 2016 is essentially unheard of, and always eyebrow-raise worthy. Tasks, on the other hand, are par for the course. Commented Jul 26, 2016 at 10:44
  • what is your sample stock size? What kind of data it contains? Commented Jul 26, 2016 at 10:45
  • Do you really think 'CheckForIllegalCrossThreadCalls = false;' is a good idea? Just don't check? Commented Jul 26, 2016 at 10:46
  • 2
    @PeterT - it still can't update the UI. You just disabled a diagnostic telling you so. You now have a program with built-in race conditions, and you may expect several hard to reproduce failures. Maybe even OOM. Commented Jul 26, 2016 at 10:55

2 Answers 2

2

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.

Sign up to request clarification or add additional context in comments.

Comments

0

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/

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.