Well i have one main form which i run like an application.On that main form i have 3 buttons which are opening another 3 forms(instances of Form2 class) which are of the same class Form2.

So i have :

Form2 form1=new Form2();
Form2 form2=new Form2();
Form2 form3=new Form2();


all of 3 instances are opened on the button click event on the mainForm.

I also have 3 backgroundworkers which are collecting data and passing them to the instances of forms with set,get properties.One background worker is for one instance.

My problem is when I open one of the instances everything works fine the instance is updated and is drawn just fine.I can see that the background worker is passing data to the instance,BUT the problem is when i close it and try to open an another instance everything freezes.The visual studio doesn't report any error everything stops.The instance that i have tried to open is beeing opened but everything is grey.

I open a instance with :form1.Visible=true
form1.show()

and i hide it with;

form1.Visible=false;
form1.Hide();

Each instance is opened and closed like this but something is not working well!!!

One more thing that might be important is that every form is updated with an event when i finish gathering the informations for drawing!!!!

Help please!!!!

Recommended Answers

All 39 Replies

So if I understand it correcly, your application has 4 windows. The main window and 3 other forms. The 3 forms are updated by backgroud worker threads.

Does the program always create all 3 forms, even if they are not visible?

Does the program always start the 3 background threads, or does it wait until the associated window is set to visible?

If the thread starts when the window is set to visible, are there any provisions to suspend or terminate the thread when the window is hidden?

Can you identify whether it is the close of the first window or the open of the second window that is causing your lockup?

How does the background thread interface with the window?

As I say the above, I seem to remember that you can (or could) generate problems when making calls into methods of the window (form) from more than one thread.

Depends a bit I guess on what exactly is being done in the background and how you've passed the forms reference to the worker thread so it knows which form to update.

Thank you for your effort i will try to answer your questions the best i can.

1.the main program only creates the main form from which 3 other forms are opened.
Each of the background workers create one instance of Form2.

all 3 background workers are started even before the main application starts(main form).after the background worker does instance of Form2 and some other variables it goes in the loop where he collects some informations and after that i call an event which updates the instance of form.The background worker is all the time collecting data and updating the instance so he never shuts down or stops.He is in infinite loop.

The identification of problem.

When i open one of those 3 windows from main window and when i close it.If i open the same window(same instance) again everything is OK but when i open a window and close it and try to open an ANOTHER window(another instance of Form2) everything stops.

Each of 3 windows are opened with button click events from main form,and the background workers are started immideatly and are running all the time collecting data from 3 instances. when the user decides to show them they should be shown with the latest data from background worker.That is the main idea.

Thanks for your help and i hope this will give you a clue of my problem

I believe the issue must be how you are assigning your forms to the worker threads (as hinted above).

However, you may need to take into account that your "form2" is not being reset each time, so, when it is reshown, it was at the end of whatever it was doing - this can have bearing as your logic may not have allowed for that.

I believe the issue must be how you are assigning your forms to the worker threads (as hinted above).

However, you may need to take into account that your "form2" is not being reset each time, so, when it is reshown, it was at the end of whatever it was doing - this can have bearing as your logic may not have allowed for that.

Well instance of Form2 is being made in Background worker class as public static.Each background worker has his own class.ALL the data is beeing sent to the Form2 class via get,set properties also the instance of Form2 is beeing sent to the Form2 class via get,set.
Everything in the Form2 class all variables are private.

So each background worker has his own instance of form2 and is updating it with data.In Form2 class is beeing called an event when the data is collected and instance is then beeing updated.Well the problem is that i can open one instance and close it as many times as i won't,but when i open one of them and close it and when i try to open ANOTHER one (not the same instance all the time) then everything stops.It looks like when i open first instance that somehow i make it Active or primare and when i close it and try to open another one it won't let me.

This is the bit that worries me

Form2 form1=new Form2();
Form2 form2=new Form2();
Form2 form3=new Form2();

if your worker makes those forms then how is it sure which form its using?

This is the bit that worries me

Form2 form1=new Form2();
Form2 form2=new Form2();
Form2 form3=new Form2();

if your worker makes those forms then how is it sure which form its using?

well the first background worker
this code is in main:

BackgroundWorker bw1 = new BackgroundWorker();
bw1.DoWork += new DoWorkEventHandler(BWClass1.bw1_DoWork);

this code down is in BWClass1!!!!

public static Form2 form1;

public static void bw1_DoWork(object sender, DoWorkEventArgs e)
{
form1=new Form2(0);
}

this code down is in BWClass2!!!!

the second background worker those the same but for

public static void bw2_DoWork(object sender, DoWorkEventArgs e)
{
form2=new Form2(1);
}

each background worker is using his one instance in function.

in constructor i am passing an argument Form2(1) which says which form should he draw and which form to update

i am doing the update of instance of Form2 in each backgroundworker for each form with get,set properties.For an example:

backgroundworker1:
form1.TEMP_PROFIL1 =temperature1;
form1.TEMP_PROFIL2 =temperature2;
form1.SREDNJA_TEMP = average_temp;
form1.MAKS_TEMP = max_temp;

backgroundworker2:
form2.TEMP_PROFIL1 =temperature1;
form2.TEMP_PROFIL2 =temperature2;
form2.SREDNJA_TEMP = average_temp;
form2.MAKS_TEMP = max_temp;

after i do my update I call an event which will draw an panel on specified Form2 instance


form1.clicked();

or

form2.clicked();


the function of the event is declared in Form2 class!!!

Hopes this clarifies a bit more!!! :)

OK, I dont see any thread handling in your code to check for the fact a UI cant be updated by anything other than the main thread.

I also am a little confused as to the Form2(0) and Form2(1) Im not sure what these parameters are for.

Form2(0) and Form2(1).
I use this argument because variables that the constructor needs to draw (sizes and stuff) are in a array so in this way the constructor knows that for first instance he must take variable of array[0] and for second instance variable from array[1].

I'm sorry i'm pretty new in all of this so i don't know what is UI? :(

And for thread handling i'm not sure what i need to use for background workers because i would like if they are all 3 working all the time and every one of them is updating a different instance of Form2.The only code they are using all 3 is the code in Form2 class for the event which is drawing on instances of Form2

UI = User Interface

normally for example, if I were writing an app that was going to do anything of value, I have update routines on my form so that other things can send it data, and irrelevant of wether those things are threaded or not, my form sorts out the update. This is done through delegates.

You often run into issues as the UI cant be updated from anything other than the main thread - so if for example, you have a progress bar and you're working through a long CSV file verifying it, and loading data, and so on, you would call the updateprogressbar function which then checks if an invoke is required and then if it is, it invokes the main thread to do that job, otherwise it does it.

So if I understood this correctly. I shouldn't do update of an instance with get,set properties which have been defined in the Form2 class but after i gather all the informations in one cycle i should call a delegate which will update my instance from the main thread

But I use the main thread to run main screen form like an application from which i am opening my instances.

and one more question is should check the invoke required of what exactly (of an instance of Form2)?

You should check for invoke on any UI component. its a good practice to get into so if you then do thread off activities you dont have to redo all your UI code. So, wether you're changing the position of a progress bar, the caption on a button, or even enabling/disabling, anything which belongs to the main thread in effect should be carefully done, as not doing so causes clashes.

Thanks for your advice but I forgot to tell you that i already have the part of code which is checking the invoke required and I have the invoke.Before when i didn't had it the visual studio reported me an error and stopped the running of code.The problem now is that i don't get any report of an error or the visual studio stops the running of application.

Here is how i do it:

in background worker i do the call:

form.clicked();

and in the Form2 class i have:

public void clicked()                                              
            {
                if (MyEvent != null)
                {
                    if (this.InvokeRequired)
                    {
                        this.Invoke(this.MyEvent); 
                    }
                    else
                    {
                        MyEvent();
                    }
                }
            }

and the function i have that does the update of form is

public void OnEvent()
{
}

as you have seen probebly in other 2 background workers i also have:

form2.clicked()

and in the 3BW:

form3.clicked();

form1 and form2 and form3 are of the same class FORM2.

BW1 updates form1
BW2 updates form2
BW3 updates form3

Thanks for the help :)

Well either somehow when you think youre closing the form the forms actually closed and gone, or, your still missing some of the thread handling..its hard to say with the code given.

Thanks, i will put locks in the code that all 3 background workers use so maybe this will help

Also i will instance all 3 instances of Form2 in main() and not in the BW-s maybe this will give some effect

You already are, because it creates it as it sends it.

Well i have tried what have you told me but unfortunately the problem is not here.I still got the freeze when i change the instances on the button click event of the main form application.

I'm going to try to give you more explanations of my code.

The first i have a main form which is the Application.Run(mainScreen)

On it there are only 2 buttons which when are clicked each of them is openig one instance of Class Form2.

i also have two background workers an they are both in infinitive loop collecting data and pasing it to one of the instances

BW1 is for form1 and BW2 is for form2.

i am passing the both forms via the e.Argument in the background worker call.

i also have an event which is called for each form when BW collects a package of data.The event updates the form and the BW collects than again and the process is in while(true) loop.


form the event i have beginInvoke and the visual studio doesn't report any error.

the instance is opened like this

private void Button1_Click(object sender, EventArgs e)
        {
                form1.Visible = true;
                form1.Show();
}

the second instance is opened the same.

They are created in void main().

I tried to create them in class MainScreen but nothing changed.

here is the code for event in background worker which updates the instance.

this is in BW1:

form1.MyEvent += new MyDelegate(form1.OnEvent);

form1.clicked();

this is in class Form2:

public void clicked()                    
                {
                    if (MyEvent != null)
                    {
                        if (this.InvokeRequired)
                        {
                            this.BeginInvoke(this.MyEvent);
                        }
                        else
                        {
                            MyEvent();
                        }
                    }
                }

If you need more of code say so but there is a big bunch of it so i don't no what to show


Thanks!!!

Still so many questions..

How do your background processes know not to work?
How is that clicked code running
Where did you do the adding of the delegate?
Whats in "MyEvent()"

1.The background workers are working all the time.I thought that that's the idea that BGW are collecting data all the time.I'm not stopping them even when i click to open one of those 2 instances.

2. The clicked code is being called from the background worker after the collection of one package of data.The function clicked() is only called for checking the required of invoke.And from it i'm calling the MyEvent();

The adding of the delegate is in the Form2 class here is the code form the delegate and the event:

public delegate void MyDelegate(); is declared between the namspace and class
public event MyDelegate MyEvent;

and the adding of delagete is in the BGW:

form1.MyEvent += new MyDelegate(form1.OnEvent);

4.In function My event I'am depending on the collected data drawing a x-x graph on the form and changing the color of pictures of form2:

For example:

for the picture:
private PictureBox Zona29 = new PictureBox();

i'm doing the change:
Zona29.Image = Properties.Resources.Cesta_crvena;

The reason I asked is every time that clicked functions called its going to add another copy of the event so you could end up with the same function called multiple times per event.

Well thats true so!!!!

Is this the right way to solve this problem:

form1.MyEvent -= new MyDelegate(form1.OnEvent);

should i put this after I call clicked();

Do you think that this is the problem why my program freezes when i switch forms!!!

If the function is going to be called more times that shouldn't block the code it will only slow it down!!!

Well it most certainly wont help it.
Try setting the event on the creation of the worker, and never again

OK i am going to do this.

thanks

Well my question is:

Should i stop the background workers when i'm switching between instances of form2.I really can't see the reason why should i do this but i'm now really out of clue why my program is behaving like this and why does it freeze when i'm switching between forms!!!

No, because if as you say the background worker works constantly irrelevant of the form being visible or not. Then the thread shouldnt ever be started or stopped accordingly. Only on creation and termination.

In your description of MyEvent, I didn't see where any data from the background worker was transferred to the form.

Could you describe a little more about that, maybe it will have a clue.

in myevent i'm comparing data and i change a color of my pictures.So this data is not shown but on the child form(instance of Form2) i have a panel and on it my drawing an graph

Graphics g = panel1.CreateGraphics();

In Myevent() i am callin an another function drawing which is drawing on panel:

drawing()
{
 g.DrawLines(pen, points); 
} 

i am calculating points for drawing from data which i get from BGW.

and the max and average temperature which i'm collecting from BGW i'm showing also on child form:

label1.Text = max_temp;
label2.Text = average_temp;

the labels are declared in Form2 class as private:

and this is one get,set in Form2 class

  public UInt16[] Alarmi_Set
                {
                    get
                    {
                        lock (this)
                        {
                            return alarms;
                        }
                    }
                    set
                    {
                        lock (this)
                        {
                            alarms = value;
                        }
                    }

                }

if you want i can give you all the code but there is a bunch of it and i'm trying to give you the most important stuff!!!

Well yesterday i tried to do something new.After i open one of the child forms and when i wish to close it I also stop the BGW which is for that child form.And then i tried to open an another child form and I could open it and the program was still running.


The only problem is that the BGW should be running all the time and not only for a while until i close it or start it again.

Well i don't have that much of experience with C# so for now this kind of experiment doesn't tell me nothing but maybe you could know where is the problem.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.