Even And Deligate

  • Thread starter Thread starter Peter
  • Start date Start date
P

Peter

I have the following code which uses Events and Deligate, I need to have a
timer in a library and update UI everytime the event fires.

but I am getting the following error in Reading method and the following
statement this.label1.Text = val.ToString();:

Cross-thread operation not valid: Control 'label1' accessed from a thread
other than the thread it was created on.

How can I fix this problem?


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using LabExampleLib;

namespace LabExample
{
public partial class Form1 : Form
{
TimerLib tl = new TimerLib();
int i = 0;

public Form1()
{
InitializeComponent();
tl.Reading += new TimerLib.Calculate(Reading);
}

void Reading(double val)
{
i++;
this.label1.Text = val.ToString();

}

private void button1_Click(object sender, EventArgs e)
{
tl.Start();
}
}
}


using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Timers;

namespace LabExampleLib
{
public class TimerLib
{
public delegate void Calculate(double val);
public event Calculate Reading;

private double i = 0;
System.Timers.Timer aTimer;

public TimerLib()
{
aTimer = new System.Timers.Timer();
aTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
}

private void OnTimedEvent(object source, ElapsedEventArgs e)
{
i++;
OnReading(i);
}

public void Start()
{
aTimer.Interval = 1000;
aTimer.Enabled = true;

}

protected void OnReading(double val)
{
if (Reading != null)
Reading(val);
}
}
}


Thank You

Peter
 
This, it seems, is a right of passage for beginning .Net users.

You are only allowed to update the UI from the UI thread. See the following
link and code excerpt from said link....

http://msdn.microsoft.com/en-us/library/ms171728(VS.80).aspx
// This method demonstrates a pattern for making thread-safe
// calls on a Windows Forms control.
//
// If the calling thread is different from the thread that
// created the TextBox control, this method creates a
// SetTextCallback and calls itself asynchronously using the
// Invoke method.
//
// If the calling thread is the same as the thread that created
// the TextBox control, the Text property is set directly.

private void SetText(string text)
{
// InvokeRequired required compares the thread ID of the
// calling thread to the thread ID of the creating thread.
// If these threads are different, it returns true.
if (this.textBox1.InvokeRequired)
{
SetTextCallback d = new SetTextCallback(SetText);
this.Invoke(d, new object[] { text });
}
else
{
this.textBox1.Text = text;
}
}
 
Section 15.4 of the article at the following link presents your alternatives
for dealing with this:http://www.codeproject.com/KB/cs/event_fundamentals..aspx

- HTH

You could replace System.Timers.Timer with System.Windows.Forms.Timer
and use the "Tick"-event instead of "Elapsed".
One of the differences between Timers.Timer and Windows.Forms.Timer is
that the former raises its events on a different thread than the one
it was created on, while the latter raises them on the same, which
makes it much more suitable to updating UIs.

hth,
Kevin Wienhold
 
DrewCE said:
This, it seems, is a right of passage for beginning .Net users.

You are only allowed to update the UI from the UI thread. See the
following link and code excerpt from said link....

http://msdn.microsoft.com/en-us/library/ms171728(VS.80).aspx
// This method demonstrates a pattern for making thread-safe
// calls on a Windows Forms control.
//
// If the calling thread is different from the thread that
// created the TextBox control, this method creates a
// SetTextCallback and calls itself asynchronously using the
// Invoke method.
//
// If the calling thread is the same as the thread that created
// the TextBox control, the Text property is set directly.

private void SetText(string text)
{
// InvokeRequired required compares the thread ID of the
// calling thread to the thread ID of the creating thread.
// If these threads are different, it returns true.
if (this.textBox1.InvokeRequired)
{
SetTextCallback d = new SetTextCallback(SetText);
this.Invoke(d, new object[] { text });
}
else
{
this.textBox1.Text = text;
}
}
Good luck said:
I have the following code which uses Events and Deligate, I need to have a
timer in a library and update UI everytime the event fires.

but I am getting the following error in Reading method and the following
statement this.label1.Text = val.ToString();:

Cross-thread operation not valid: Control 'label1' accessed from a thread
other than the thread it was created on.

How can I fix this problem?


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using LabExampleLib;

namespace LabExample
{
public partial class Form1 : Form
{
TimerLib tl = new TimerLib();
int i = 0;

public Form1()
{
InitializeComponent();
tl.Reading += new TimerLib.Calculate(Reading);
}

void Reading(double val)
{
i++;
this.label1.Text = val.ToString();

}

private void button1_Click(object sender, EventArgs e)
{
tl.Start();
}
}
}


using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Timers;

namespace LabExampleLib
{
public class TimerLib
{
public delegate void Calculate(double val);
public event Calculate Reading;

private double i = 0;
System.Timers.Timer aTimer;

public TimerLib()
{
aTimer = new System.Timers.Timer();
aTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
}

private void OnTimedEvent(object source, ElapsedEventArgs e)
{
i++;
OnReading(i);
}

public void Start()
{
aTimer.Interval = 1000;
aTimer.Enabled = true;

}

protected void OnReading(double val)
{
if (Reading != null)
Reading(val);
}
}
}


Thank You

Peter

Thanks the problem is solved.
 
Back
Top