# Do you use global variables?



## MrSeanKon (Oct 9, 2007)

Yes I do.
It help me cos I am not a professional programmer  so I get confused with many function arguments.
But they are the source of many bugs.
Anyway what's your opinion?


----------



## magibeg (Oct 10, 2007)

I try to avoid using them as often as possible. As programs get larger and more complex i find its easier to keep things in small pieces. With global variables if someone else looks at your code and changes a value in it by mistake it could make your program blow up all over the place but if its all very local then you can usually narrow it down quite quickly.


----------



## MrSeanKon (Oct 17, 2007)

Yeah most of programmers (especially professionals) avoid to use global variables.
But it is one feature useful (compare goto statement) and if you are careful it helps.
Of course I have not written something enormous!


----------



## Kreij (Oct 17, 2007)

Sometimes there is a need to use global variable, however, it is usually a good practice to try to avoid them.  If you are trying to keep tight encapsulation of your code so that a portion of the program cannot change some underlying data that another portion may need you want to avoid them at all costs. This becomes really apparant when writing multi-threaded code.

There are cases where globals make no difference. Let's say you are using a database connection and you want to put the connection string into a static variable that will never  changed. This is fine as any portion of the program that needs to read the value of the connection string can do so at any time, without you having to pass the value into the respective portion of the code (even across private classes in the same namespace).

There are even two levels of global variables, user level or application level. Basically what this means is that when two users instances are run, they each have a copy of the global variable to themselves and cannot change each others. App level means that there is only one copy of the variable that any instance can use. This comes in handy for setting things like user preferences in applications that differ across user instances (like color settings).

All that being said, if it is a simple single-threaded app and a global reduces your coding time and makes life easier ... go for it


----------



## MrSeanKon (Oct 26, 2007)

Nice analysis Kreij but the problem is that I am rewritting some parts as you can see *here* from single threading to multithreading and I am confused!
Until now global variables help me to share the first multithreading applications (OcBible updates) but I am wondering what should I do.....


----------



## Kreij (Oct 26, 2007)

One of the problems with Mult-Threaded (MT) code is that you very often cannot determine the specific time that a thread will end or update a value. If the global variable is only being read, then it does not matter. If it is being read *and* written to by both threads, it could produce all kinds of erroneous values (and could be quite difficult to debug if you were not sure what was happening).

One thing you could do is create a delegate and an event handler for the threads. When something occured in the thread that you want the other thread to know about you could fire off the event and have the other tread listening for it (and vice-versa). You could then control access timing to the variable (or whatever).

There are problably better ways to do this (than using delegates) written into the MT libraries, but not having done much with MT code, I am not sure how to do it.

If you try several things and get nowhere, let me know and I will help you dig into it.
Post some actual code to this thread if you want.

Remember two Googlers are better than one ! 

BTW, did you read the page that W1z linked to in the other thread? If covers thread parameter passing .


----------



## Kreij (Oct 26, 2007)

OK, MrSean ... here you go.

In a multi-threaded Windows Forms application, it's illegal to call a method or property on a control from any thread other than the one that created it.  This is a problem as you want to not only pass a parameter in, but send a resultant one back out.

This is where the class BackgroundWorker comes in handy. Without getting into to much detail, the BackgroundWorker lets you update windows form controls (or whatever) from the thread even thought the location of the object to update is not in the same thread.


```
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
[color=Green]// You need the next two lines in your "using" declarations[/color]
[b]using System.Threading;
using System.Runtime.Remoting.Messaging;[/b]

namespace ThreadTest
{
    public partial class Form1 : Form
    {
        [color=Green]// Create an instance of a BackgroundWorker thread[/color]
        private static BackgroundWorker bgw = new BackgroundWorker();

        public Form1()
        {
            InitializeComponent();
            [color=Green]// Override the Do_Work and RunWorkerCompleted methods so you can do what you want[/color]
            bgw.DoWork += new DoWorkEventHandler(bgw_DoWork);
            bgw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bgw_RunWorkerCompleted);
        }

        void bgw_DoWork(object sender, DoWorkEventArgs e)
        {
            [color=Green]// This is just a bogus point to compare the incoming point to[/color]
            Point pointToHit = new Point(20, 20);

            [color=Green]// If the incoming point equals the bogus one, its a hit ![/color]
            [color=Green]e.Arguement is the point sent in when you called the RunWorkerAsync method in the button1_Click override[/color]
            if (pointToHit == (Point)e.Argument)
            {
                e.Result = true;
            }
            else
            {
                e.Result = false;
            }
        }

        void bgw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            [color=Green]// Put the result of the hit test in the TextBox on the main form
            // This is where the BackgroundWorker makes things easy.[/color]
            textBox1.Text = e.Result.ToString();
        }

        [color=Green]This is overridden in the InitializeComponents method (not shown)[/color]
        private void button1_Click(object sender, EventArgs e)
        {
            [color=Green]// Fire off the BackgroundWorker thread with a test point[/color]
            bgw.RunWorkerAsync(new Point(10, 10));
        }
    }
}
```

All this code does it check to see if you scored a "hit" after you press the button and write true or false to a TextBox.
In the case shown it will always return false because I am comparing point(10,10) to point(20,20)

I got this information from this article. There is a lot more that the BackgroundWorker class can do for you.

Let me know if this helps.


----------



## Oliver_FF (Oct 26, 2007)

If you are working in a language like Java or possibly C#  then you should use accessors to access global variables, and wrap those within classes.


public class MyClass
{
    Private Object someAccessibleVariable;

   public MyClass()  {  }

   public Object getVariable()
   {
       return someAccessibleVariable;
   }

   public void setVariable(Object newVariable)
   {
       someAccessibleVariable = newVariable;
   }
}



When you call getVariable you don't get the actual someAccessibleVariable back, but you get  a COPY of someAccessibleVariable. Calling the method outside of the class will get you the object, but if you modify it your only changing the new object, not the original someAccessibleVariable. Good for decoupling code as it means each class is responsible for modifying it's own variables - one class cannot directly modify another class. Stops code from breaking after changes are made, etc.


----------



## Kreij (Oct 26, 2007)

Oliver_FF said:


> If you are working in a language like Java or possibly C#  then you should use accessors to access global variables, and wrap those within classes.



Yes, but you can't call a class' property (accessor) methods from another thread directly.
That's what MrSean is trying to do.

Edit : On another note, you can't access a parents property or accessor methods from a child it has created either (well not easily anyway).
That has to be done using delegates also.


----------



## MrSeanKon (Oct 29, 2007)

Damn (it is 10000000% my fault)  the above posts should be posted to other TechPowerUp! thread.
I made a mess 
*Look this thread folks* it has a similar discussion and of course my problem.
To summarize I use global variables cos:
1) I cannot pass/receive parameters to/from threads.
2) It is not easy to pass many different parameters --> the OCUK thread.
Anyway we should stop discussing about threads here to help the readers.
I am trying to be a non FORTRAN programmer! 
I used this language for a long time so I have some bad habbits!


----------

