Problems with Delegates

T

traafat

Hello guys,

i am having a problem using Delegates, i am pretty new to C# , i am
starting to fall in love with it its really good language (coming from
Java and Delphi),

now i am working on an application where i have a label on a form and
then i have a separate class in separate CS file (ie., Form1.cs and
myClass.cs)

what i am trying to do : i wanted to update label1.Text every tick of
a timer with the format 00:00 next tick 00:01, then next tick 00:02
and so on

so in my Class there is a timer(System.Timers.Timer/
System.Threading.Timer/System.Windows.Forms.Timer) and i am trying to
update the label1 in form1 using the following :

Form1 :
-----------
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;


namespace WindowsApplication2
{

public partial class Form1 : Form
{

public Form1()
{
InitializeComponent();
}
public void setlabeltext(Label lbl, String strValue)
{
lbl.Text = strValue;
}
private void Form1_Load(object sender, EventArgs e)
{
Class1 myClass = new Class1();
myClass.startCall();
}
}
}


myClass:
--------------
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using Timers = System.Windows.Forms.Timer;

namespace WindowsApplication2
{
class Class1
{
Form1 form1 = new Form1();

Timers timoz = new Timers();


public void timoz_Tick(object sender, EventArgs e)
{
ThreadSafeSetLable(form1.label1,
DateTime.Now.Subtract(DateTime.Now).ToString());
}



private void ThreadSafeSetLable(Label lbl, string value)
{
if (form1.InvokeRequired)
{

form1.Invoke(new SetString(form1.setlabeltext), new
object[] { lbl, value });
}
else
{
form1.setlabeltext(lbl, value);

}
}




private delegate void SetString(Label txtBox, string
strValue);

public void startCall()
{
timoz.Interval = 1000;
timoz.Start();
timoz.Tick += new EventHandler(timoz_Tick);
}
}
}

this is not working i dont know why , it compiles no problem , in the
debugging the label1.text is changing to 00:00:00 but runtime i dont
see that , plus the form1.InvokeRequired never gets to "true" , i do
realize that i am missing something but i dont know what , can i have
help on that ? thanx
 
P

Peter Duniho

[...]
this is not working i dont know why , it compiles no problem , in the
debugging the label1.text is changing to 00:00:00 but runtime i dont
see that , plus the form1.InvokeRequired never gets to "true" , i do
realize that i am missing something but i dont know what , can i have
help on that ? thanx

Well, the most obvious issue that I see is that the form on which you're
setting the text isn't the same form that you're displaying. You need to
pass "this" in to the Class1 somehow (perhaps via the constructor, for
example) so that it can use *that* reference, rather than creating a new
form (as it does now). This for sure explains why the text on the
displayed form isn't updated, and probably explains why
form1.InvokeRequired is never true (since form1 isn't shown yet,
cross-thread invocation may not be a problem yet).

One other thing I'll point out is that the mechanism you're using,
checking InvokeRequired, is only necessary if you use the same method for
the actual Invoke. That is, if in ThreadSafeSetLabel your delegate that
you Invoke on the form is created from ThreadSafeSetLabel itself, then you
need the check. But if the thread-safe method is invoking some other
method, then you don't need to check InvokeRequired. You can just always
create the delegate and then invoke it on the form.

Pete
 
C

CSharper

[...]
this is not working i dont know why , it compiles no problem , in the
debugging the label1.text is changing to 00:00:00 but runtime i dont
see that , plus the form1.InvokeRequired never gets to "true" , i do
realize that i am missing something but i dont know what , can i have
help on that ? thanx

Well, the most obvious issue that I see is that the form on which you're
setting the text isn't the same form that you're displaying. You need to
pass "this" in to the Class1 somehow (perhaps via the constructor, for
example) so that it can use *that* reference, rather than creating a new
form (as it does now). This for sure explains why the text on the
displayed form isn't updated, and probably explains why
form1.InvokeRequired is never true (since form1 isn't shown yet,
cross-thread invocation may not be a problem yet).

One other thing I'll point out is that the mechanism you're using,
checking InvokeRequired, is only necessary if you use the same method for
the actual Invoke. That is, if in ThreadSafeSetLabel your delegate that
you Invoke on the form is created from ThreadSafeSetLabel itself, then you
need the check. But if the thread-safe method is invoking some other
method, then you don't need to check InvokeRequired. You can just always
create the delegate and then invoke it on the form.

Pete

Thank you very much for the fast reply , OMG i am really loving this
language and its support i can tell its booming :)
anyway would mind if you show me an example of how to pass "this"
using Class1?

like should i put

public void Class1(Form1 frm)
{

}

and then in form1 on load i put,
private void Form1_Load(object sender, EventArgs e)
{
Class1 myClass = new Class1(form1);
myClass.startCall();
}
is that how it is ?
can you please provide me with examples?

thanks
 
A

Alberto Poblacion

CSharper said:
[...]
anyway would mind if you show me an example of how to pass "this"
using Class1?
[...]
and then in form1 on load i put,
private void Form1_Load(object sender, EventArgs e)
{
Class1 myClass = new Class1(form1);
[...]

No, you would do it like this:

Class1 myClass = new Class1(this);

Since this sentence is written inside your executing Form1, the "this"
will pass the specific instance of the form1 that Class1 needs to receive.
 
C

CSharper

[...]
anyway would mind if you show me an example of how to pass "this"
using Class1?
[...]
and then in form1 on load i put,
private void Form1_Load(object sender, EventArgs e)
{
Class1 myClass = new Class1(form1);
[...]

No, you would do it like this:

Class1 myClass = new Class1(this);

Since this sentence is written inside your executing Form1, the "this"
will pass the specific instance of the form1 that Class1 needs to receive.

yea, but how in Class1 i would handle form1?

i mean how should i adjust Class1 then ?
 
A

Alberto Poblacion

CSharper said:
yea, but how in Class1 i would handle form1?

i mean how should i adjust Class1 then ?

using Timers = System.Windows.Forms.Timer;

public class Class1
{
private Form1 theForm;

public void Class1(Form1 frm)
{
theForm = frm;

Timers timoz = new Timers();
timoz.Interval = 1000;
timoz.Tick += new EventHandler(timoz_Tick);
timoz.Start();
}
....
public void timoz_Tick(object sender, EventArgs e)
{
theForm.setlabeltext(theForm.Label1, theValue);
}
}


Note that you don't have to use Invoke or BeginInvoke. This is because you
are using a System.Windows.Forms.Timer, which fires the event in the same
thread as the form is running. If you were using a System.Timers.Timer or a
System.Threading.Timer you would have to do the thread marshalling with one
of those methods.
 
C

CSharper

using Timers = System.Windows.Forms.Timer;

public class Class1
{
private Form1 theForm;

public void Class1(Form1 frm)
{
theForm = frm;

Timers timoz = new Timers();
timoz.Interval = 1000;
timoz.Tick += new EventHandler(timoz_Tick);
timoz.Start();
}
...
public void timoz_Tick(object sender, EventArgs e)
{
theForm.setlabeltext(theForm.Label1, theValue);
}

}

Note that you don't have to use Invoke or BeginInvoke. This is because you
are using a System.Windows.Forms.Timer, which fires the event in the same
thread as the form is running. If you were using a System.Timers.Timer or a
System.Threading.Timer you would have to do the thread marshalling with one
of those methods.

thanx much you are the best it works now :)
 
C

Christof Nordiek

Hi,

about the InvokeRequired question.
Your using the Windows.Forms.Timer. This uses the GUI message loop to notify
ticks. So the Tick event gets called on the UI-Thred like other GUI events.
That's why Invoke is never required in your example.

Christof
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top