none
126,000 lines of code - System.OutOfMemoryException

    Question

  • Hi,

    I do have a question. In my MainPage.xaml.cs file, I am on the 126,000:th line now coding. Sometimes when I compile I get this below exception that tell about OutOfMemoryException.

    I wonder if this depends on the big amount of code. I have 3.5 GB of RAM and there is 1.5 GB Free RAM when I compile. My XAML contain of approx: 15,000 lines of code.

    Source file 'D:\Documents and Settings\A\My Documents\Visual Studio 2010\Projects\thisProj\thisProj\MainPage.xaml.cs' could not be opened ('Exception of type 'System.OutOfMemoryException' was thrown.')

    Friday, October 07, 2011 10:46 AM

All replies

  • You're not expecting any response other than "break up your code" are you? Just out of curiousity, why haven't you already?

    Friday, October 07, 2011 11:32 AM
  • Really!? 126000 lines of code? You have more problems with your code than VS can't open it. Tou should read about OOP and organize your code. http://www.codeproject.com/KB/architecture/OOP_Concepts_and_manymore.aspx

    Friday, October 07, 2011 11:33 AM
  • Yes I know it is much but I have just kept writing code and dont exactly know how to "break up this code" in parts. For example. I have one design "Mainpage.xaml" wih all its controls everywhere.

    If I have a buttoncontrol that executes code, I have put them in Mainpage.xaml.cs.

    How will I put that code in another file for example. Let us say ex: Mainpage2.xaml.cs ? Because Mainpage.xaml and Mainpage.xaml.cs are conntected to eachother or is it possible to have differenct .xaml.cs files connected to the same .xaml file?

    Perheps this is obvious how to do but have never looked into it?

    Friday, October 07, 2011 4:12 PM
  • Does the MainPage.cs have more than one class in it?

    Friday, October 07, 2011 6:50 PM
  • No I dont think so, I have all my code like it looks below.

    I wonder if it is possible to have for example 2 different xaml.cs files to this XAML file? In that case, it perheps is possible to put half of the code in each of them?

    //XAML
    <UserControl x:Class="myProject.MainPage"
    	      xmlns:my="clr-namespace:myProject"
    </UserControl>
    
    
    
    //XAML.CS
    namespace myProject
    {
        public partial class MainPage : UserControl
        {
            //All lines here
        }
    }
    
    Friday, October 07, 2011 7:40 PM
  • Silvers,

    you can use partial class to cut your class code in many files.

    It's working with Embarcadero Prism, but I don't have try it in C#, but it should work.

    http://msdn.microsoft.com/en-us/library/wa80x488%28VS.80%29.aspx

    Patrick

    Saturday, October 08, 2011 1:03 AM
  • Thanks for this information. I have looked into it but dont get exactly how to set this up with partial class, so I think it is best to ask first.

    I will take a real life example of what I would like to do. I have my XAML file with 2 button controls. That is fine. Now I have those Click events in the codebehind file Mainpage.xaml.cs file.

    The ideal thing now would be to have the button1_Click event in Mainpage.xaml.cs and now create a new file, let us say Mainpage2.xaml.cs and put the button2_Click event in that file.

    Is this possible to do and how would I do this practically by modifying the below code?

    //Mainpage.xaml
    <Button x:Name="button1" Content="button1" Click="button1_Click"  />
    <Button x:Name="button2" Content="button2" Click="button2_Click"  />
    
    
    
    //Mainpage.xaml.cs
    namespace myProject
    {
        public partial class MainPage : UserControl
        {
    
            private void button1_Click(object sender, RoutedEventArgs e)
            {
                //do something
            }
            private void button2_Click(object sender, RoutedEventArgs e)
            {
                //do something
            }
        }
    }
    Saturday, October 08, 2011 5:03 PM
  • I don't think the partial class is going to help you because the partial class is a pre-processor "trick" in which the different partial files will be combined in memory prior to compilation - probably leaving you with the same problem.  Let's try to get a couple steps closer to solving the real problem which is that you have one class that does WAY too much.  One way to help with this would be to create classes to perform the actions that are currently being handled directly in your code.  To make the example a little more pertinent, let's say that button1 is called saveButton has many lines of code behind it.  You could create a class responsible for handling the save operation with a method that accepts the data it needs to make decisions and perform its function in parameters.  The code behind buttonSave_Click would only instatiate the object and call its Save method.  You probably do not want to create a class for every operation, but look for ways to group the operations logically.

    Saturday, October 08, 2011 11:07 PM
  • Hello,

    after splitting the class, your code should look like:

    //Mainpage.xaml.cs
    namespace myProject
    {
        public partial class MainPage : UserControl
        {
    
            private void button1_Click(object sender, RoutedEventArgs e)
            {
                //do something
            }
        }
    }
    //Mainpage2.xaml.cs
    namespace myProject
    {
        public partial class MainPage : UserControl
        {
    
            private void button2_Click(object sender, RoutedEventArgs e)
            {
                //do something
            }
        }
    }

    Patrick

    Sunday, October 09, 2011 1:03 AM
  • >> One way to help with this would be to create classes to perform the actions that are currently being handled directly in your code


    Perheps this is the way to go then instead of partial class. I have never worked with classes in that way where I create them myself so I am not sure of how to do this actually.

    The only thing that I have done is to call a function like below, where I pass along variables needed in that function.
    Perheps this is a good start to know how to create a class instead of this function and have the same functionality where I show a messageBox in the end?
    I also wonder if a class is a new .cs file which I assume? I would be happy for help how to achive this.

            private void button1_Click(object sender, RoutedEventArgs e)
            {
                String one = "Hello1";
                String two = "Hello2";
                String three = "Hello3";
    
                doSomething(one, two, three);
            }
    
            void doSomething(String one, String two, String three)
            {
                //Show messagebox with those variables one, two and three
                  MessageBox.Show(one + "," + two + "," + three);
            }
    Sunday, October 09, 2011 6:31 PM
  • I also wonder if a class is a new .cs file which I assume?

    It doesn't have to be in a new file (unless you're programming in a POS language starting with J designed by an overratted hack.) Since your current file has 126,000 lines, creating a new one is a good idea. Your classes should attempt to encapsulate related functionality. So to get started, just move some of your existing functions into a new class. One strategy for doing this would be to move one or two member variables that are only accessed by a couple functions to a separate class.

    Sunday, October 09, 2011 6:55 PM
  • Not ideal organization but I want to start with baby steps, so let's start by right-click your project and selecting Add -> New Folder.  Name this folder MainPageClasses.  Now right-click this folder and select Add...Class.  With names like "button1" and "doSomething" I don't know what the class will best be named, but try to find a noun the describes something that will be responsible for the group of operations we're going to put in this class.  For lack of a better term, I will refer to it as Calculator.  Add your method to this class, remembering that you can no longer directly interact with your page controls, so you need to pass in the data and return data used to populate controls.  Here is an example of what a Calculate  method might look like:

     

    namespace MyApp.MainPageClasses
    {
    public class Calculator
    {
    public int Calculate(string anImportantValue, string anotherImportantValue)
    {
    // a bunch of code using the passed value to calculate return value
    return 42;
    }
    }
    }

    and how it might be used from your page:

     

    public void calculateButton_Click(object sender, RoutedEventArgs e)
    {
         resultTextBlock.Text = new Calculator().Calculate(valueTextBox.Text, anotherValueTextBox.Text).ToString();
    }
    Sunday, October 09, 2011 7:03 PM
  • Thanks alot for those baby steps, it made me understand this perfectly. Some is the same idéa of calling a function but here you can create parameters in the class so they can be called like that.

    I have to ask something here. The thing is that I want to move big blocks of code into those classes. For example I have one code that is 15,000 lines that all resides in a Backgroundworker where this process can take hours.

    Now I wonder if you can use a Backgroundworker in this class like I have started it out below?. When I declare the below, the "thisString" is underlined in RED. (However to mention here is that I would need to return a value like in ReportProgress for the backgroundworker and not just a return in the end of code)

    The thing I would like to accomplish is to send Strings to the backgroundworker like below and make this backgroundworker start working (RunAsync())

    namespace First.Calculator
    {
        public class Calculate
        {
             
            public BackgroundWorker BGWorker1(String getString1, String getString2)
            {
                
                     
                     //All code goes here
                     
                     return "thisString";
                 
            } 
    
        }
    }
    
    
            public void calculateButton_Click(object sender, RoutedEventArgs e) 
            {
                Calculator.Calculate ts = new Calculator.Calculate();
                String returnString = ts.Calculate("sendString1", "sendString2");
    
                MessageBox.Show(returnString); //We return this string: "thisString"
            }
    
    Monday, October 10, 2011 9:10 AM
  • You have to remember that the background process is operating asynchronously, so the return won't be available.  One solution is to instead of returning a string here return void and accept a parameter of type Action<string>.  In your Completed event for the worker you can call the passed method.  Without the async stuff here's a quick sample:

    void button1_Click(object sender, RoutedEventArgs args)
    {
       doSomething( result => {MessageBox.Show(result);} );
    }
    
    void doSomething(Action<string> callBack)
    {
        // do work here
        callBack("done");
    }
    Monday, October 10, 2011 9:20 AM
  • Thanks again, I am not exactly sure of what I am doing now. I dont know the difference between a string and a Action<string>.

    I have assumed that the backgroundworker can be declared like below. So we have started the process that will be no problem if I assume the below.

    If we take the scenario I have now, is that I need to report back a String, "1 %" on the UI thread that will be showed in a TextBlock, so this happens all the time. How can this be done since the doSomething() was called by a button control.

    I am not sure how to think correctly here:

            void button1_Click(object sender, RoutedEventArgs args)
            {
                Calculator.Calculate ts = new Calculator.Calculate();
                ts.doSomething(result => { MessageBox.Show(result); }); 
            }
    
    
    namespace First.Calculator
    {
        public class Calculate
        {
            BackgroundWorker BGWorker = new BackgroundWorker();
            public void doSomething(Action<string> callBack) 
            {            
                BGWorker.WorkerSupportsCancellation = true;
                BGWorker.WorkerReportsProgress = true;
                BGWorker.DoWork += new DoWorkEventHandler(BGWorker_DoWork);
                BGWorker.ProgressChanged += new ProgressChangedEventHandler(BGWorker_ProgressChanged);
                BGWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(BGWorker_RunWorkerCompleted);
    
                if (BGWorker.IsBusy == false)
                {
                    BGWorker.RunWorkerAsync();
                }
            }
    
            private void BGWorker_DoWork(object sender, DoWorkEventArgs e)
            {
                //All code goes here
                BGWorker.ReportProgress(1);
            }
            private void BGWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
            {
                if (e.ProgressPercentage == 1)
                {
                    //How to report back: "1 %" to the UI thread here?
                }
            }
            private void BGWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
            {
    
            }
        }
    }
    
    Monday, October 10, 2011 9:46 AM
  • Action<string> is an executable method that accepts a string as its only parameter and has no return value (void), so it effectively in the course of asynchrous programming can be used to communicate a result or progress.  I would likely use an Action<int> to report progress (passing a lambda that updates the progress control).  Fit into your example, it would be something like this (I didn't test harness the code):

            void button1_Click(object sender, RoutedEventArgs args)
            {
                Calculator.Calculate ts = new Calculator.Calculate();
                ts.doSomething(result => { MessageBox.Show(result); }
                    , progress => { myProgressBar.Value = progress } ); 
            }
    
    
    namespace First.Calculator
    {
        public class Calculate
        {
            public void doSomething(Action<string> completionCallBack, Action<int> progressCallBack) 
            {
                BackgroundWorker BGWorker = new BackgroundWorker();
                BGWorker.WorkerSupportsCancellation = true;
                BGWorker.WorkerReportsProgress = true;
                BGWorker.DoWork += new DoWorkEventHandler(BGWorker_DoWork);
                BGWorker.ProgressChanged += (sender, args) => { progressCallBack( e.ProgressPercentage ); };
                // next line should check for cancellation and error, but abbreviated here
                BGWorker.RunWorkerCompleted += (sender, args) => { completionCallBack( args.Result.ToString() ); };
    
                if (BGWorker.IsBusy == false)
                {
                    BGWorker.RunWorkerAsync();
                }
            }
    
            private void BGWorker_DoWork(object sender, DoWorkEventArgs e)
            {
                //All code goes here
                BackgroundWorker worker = (BackgroundWorker) sender;
                worker.ReportProgress(1);
            }
        }
    }
    
    Tuesday, October 11, 2011 6:11 PM
  • Hi, thank you for that answer,

    I have now started trying to understand the example and see if I can adapt it to my real code. Though I still have a few questionmarks before I can start redoing the code I have.

    1. When I put your code in the compiler, the compiler says that "e" doesn´t exist in the current context for this first line below.

    2. Also in the progress, I would need to pass back a string rather than an int that contains some information that will be updated in a TextBlock. Is it possible to pass back a string in the reportprogres for the code below?

    3. I am not sure if I miss something but I will need to pass on a string to the backgroundworker that will be catched up there and needed in the _DoWork. How will I pass on a String to the _DoWork from the button1_Click?

    Thank you

    BGWorker.ProgressChanged += (sender, args) => { progressCallBack(e.ProgressPercentage); };
    
    
    private void BGWorker_DoWork(object sender, DoWorkEventArgs e)
            {
                //All code goes here 
                BackgroundWorker worker = (BackgroundWorker)sender;
                worker.ReportProgress(1);
            } 
    Wednesday, October 26, 2011 6:07 AM
  • That's what I get for typing code directly into the message :)

    The first line should have been:

    BGWorker.ProgressChanged += (sender, args) => { progressCallBack(args.ProgressPercentage); };

    For passing a string, modify the progressCallback parameter to be Action<string> instead of Action<int>

    You need to define a parameter in your method for each piece of information used in the code and pass those values when calling the method.

    Wednesday, October 26, 2011 6:21 AM
  • Thanks for so fast answer,

    I am sorry if ask again. This is really new code for me any detail makes me a bit confused now. So I try to ask.

    I changed it to args.ProgressPercentege in combination that I also changed to Action<string> progressCallBack but then when doing the last it now expects a string instead so the whole "progressCallBack(args.ProgressPercentage)" is now underlined that indicates an int. Best thing to ask what could be needed to do?

    Also I am not exactly sure of how I will pass along a string to the backgroundworker from the button1_Click event. I wonder if I will do something like below where I try to pass along: "passThisString " (One string will be okay to send in this case where I will put all needed variables) but how will I catch it in the backgroundworker?

            void button1_Click(object sender, RoutedEventArgs args) 
            { 
                String passThisString = "InformationToPass";
                Calculator.Calculate ts = new Calculator.Calculate(passThisString); 
                ts.doSomething(result => { MessageBox.Show(result); } 
                    , progress => { myProgressBar.Value = progress } );  
            }
    
            public void doSomething(Action<string> completionCallBack, Action<string> progressCallBack)
            {
                BGWorker.ProgressChanged += (sender, args) => { progressCallBack(args.ProgressPercentage); };
            }
            private void BGWorker_DoWork(object sender, DoWorkEventArgs e)
            {
                //How to catch up passThisString here?
    
                //All code goes here 
                BackgroundWorker worker = (BackgroundWorker)sender;
                worker.ReportProgress(1);
            } 
    Wednesday, October 26, 2011 6:47 AM
  • Can you paste your code here so we can have a look?

     

     

    (joke)

    Wednesday, October 26, 2011 9:30 AM
  • Hello Silvers

    Consider using MVVM..all the event handler logic would be going into the view models(using commanding)..Also you can split the code into multiple view models for the same view..that way your app would be easy to maintain...126000 lines of code behind is simply unacceptable...

    Thursday, October 27, 2011 1:47 AM