Re: This program is not thread safe and cause run time error in debug mode
- From: "Tony Johansson" <johansson.andersson@xxxxxxxxx>
- Date: Mon, 04 Feb 2008 21:09:06 GMT
Hello!
If I have a control in the form that is accessed by a different thread then
the one that was used when the control was created
I get "Cross-thread operation not valid: Control 'digital' accessed
from a thread other than the thread it was created on." which this mail is
about
As I have written this error appear only in debug mode and not in release
mode.
So the debugger inform me that usage of thread is not correct.
Now to my question if this error is not corrected what would the
consequences be ?
What symptom could I get when this program is put into production because of
incorrect usage of threads.
//Tony
"Sergey Zyuzin" <forever.zet@xxxxxxxxx> skrev i meddelandet
news:99559205-33b5-4fde-9eb9-a98099c20291@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
On 3 ÆÅ×, 12:13, "Tony Johansson" <johansson.anders...@xxxxxxxxx>
wrote:
Hello!
Below is a complete program that works fine in release mode but cause run
time errror in debug mode
because of "Cross-thread operation not valid: Control 'digital' accessed
from a thread
other than the thread it was created on."
The windows program below consist of these 4 classes
1. Program
2. Form
3. Clock
4 Ticker
Now to my questions.
Info the program below is a copy from a book called Visual studio 2005
from
Microsoft.
1. The first question is that the program below works fine in release mode
but cause
run time error in debug mode. So because of that I assume that the thread
handling must be different
between debug mode and release mode?
2.Is it always advisable to fix run time error of the kind that I have in
this program?
3. My third question is how do I fix the program with the same
functionallity
which mean that I can subscribe to the event and unsubscribe to the event
without causing
run time error?
4. Assume I have written a program and only run it in release mode because
it works as expected. In this case I will never
discover that there exist a problem with thead handling as in my example.
So
is the solution to find problem
with thread to always run these program through the debugger?
The first class is the Program where the main is located
// *** Program ****
#region Using directives
using System;
using System.Collections.Generic;
using System.Windows.Forms;
#endregion
namespace Delegates
{
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.Run(new Form1());
}
}
} //end class Program
The second class is the Form1 class
// Form1 start
#region Using directives
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Windows.Forms;
#endregion
namespace Delegates
{
partial class Form1 : Form
{
private Clock clock;
public Form1()
{
InitializeComponent();
clock = new Clock(digital);
}
private void start_Click(object sender, System.EventArgs e)
{ clock.Start(); }
private void stop_Click(object sender, System.EventArgs e)
{ clock.Stop(); }
} // end class Form1
}
Here I have the Form1.designer part
// ** Form1 Designer ***
Namespace Delegates
{
partial class Form1
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.stop = new System.Windows.Forms.Button();
this.start = new System.Windows.Forms.Button();
this.digital = new System.Windows.Forms.TextBox();
this.SuspendLayout();
//
// stop
//
this.stop.Location = new System.Drawing.Point(144, 67);
this.stop.Name = "stop";
this.stop.Size = new System.Drawing.Size(48, 23);
this.stop.TabIndex = 5;
this.stop.Text = "Stop";
this.stop.Click += new System.EventHandler(this.stop_Click);
//
// start
//
this.start.Location = new System.Drawing.Point(72, 67);
this.start.Name = "start";
this.start.Size = new System.Drawing.Size(56, 23);
this.start.TabIndex = 4;
this.start.Text = "Start";
this.start.Click += new System.EventHandler(this.start_Click);
//
// digital
//
this.digital.Enabled = false;
this.digital.Font = new System.Drawing.Font("Courier New",
20.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point,
((byte)(0)));
this.digital.Location = new System.Drawing.Point(56, 19);
this.digital.Name = "digital";
this.digital.Size = new System.Drawing.Size(152, 38);
this.digital.TabIndex = 3;
this.digital.Text = "04:11:34";
this.digital.TextAlign =
System.Windows.Forms.HorizontalAlignment.Center;
//
// Form1
//
this.ClientSize = new System.Drawing.Size(264, 109);
this.Controls.Add(this.stop);
this.Controls.Add(this.start);
this.Controls.Add(this.digital);
this.Name = "Form1";
this.Text = "Digital Clock";
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.Button stop;
private System.Windows.Forms.Button start;
private System.Windows.Forms.TextBox digital;
}
}
The third class is the Clock class
// ** Clock ***
using System.Windows.Forms;
namespace Delegates
{
class Clock
{
private Ticker pulsed = new Ticker();
private TextBox display;
public Clock(TextBox display)
{ this.display = display; }
public void Start()
{ pulsed.tick += new Ticker.Tick(RefreshTime); }
public void Stop()
{ pulsed.tick -= new Ticker.Tick(RefreshTime); }
private void RefreshTime(int hh, int mm, int ss)
{ display.Text = string.Format("{0:D2}:{1:D2}:{2:D2}", hh, mm,
); }
}
//Start class Ticker
Namespace Delegates
{
using System.Timers;
class Ticker
{
public delegate void Tick(int hh, int mm, int ss);
public event Tick tick;
private Timer ticking = new Timer();
public Ticker()
{
ticking.Elapsed += new ElapsedEventHandler(OnTimedElapsed);
ticking.Interval = 1000;
ticking.Enabled = true;
}
private void Notify(int hours, int minutes, int seconds)
{ if (tick != null) tick(hours, minutes, seconds); }
private void OnTimedElapsed(object source, ElapsedEventArgs args)
{
int hh = args.SignalTime.Hour;
int mm = args.SignalTime.Minute;
int ss = args.SignalTime.Second;
Notify(hh, mm, ss); // call notify
}
}
} // end class Ticker- óËÒÙÔØ ÃÉÔÉÒÕÅÍÙÊ ÔÅËÓÔ -
- ðÏËÁÚÁÔØ ÃÉÔÉÒÕÅÍÙÊ ÔÅËÓÔ -
Hi Tony,
1. Thread handling should be the same in both release and debug modes.
However defects may show themselves differently in debug and
release.
3. As Marc said, you should set a control's properties from UI thread,
while
RefreshTime method is called from another thread when timer fires.
One option to fix the problem is to modify your RefreshData method in
the following way:
private void RefreshTime(int hh, int mm, int ss)
{
string text = string.Format("{0:D2}:{1:D2}:{2:D2}", hh, mm, ss);
display.BeginInvoke(new MethodInvoker(delegate { display.Text =
text; }));
}
4. Threading issues are usually difficult to find. They may appear
very rarely.
Many of multithreading issues can be found during stress/load
testing.
I usually start to suspect that there's something wrong with
multithreading if I
get errors that "can never occur".
Thanks,
Sergey
.
- Follow-Ups:
- Re: This program is not thread safe and cause run time error in debug mode
- From: Sergey Zyuzin
- Re: This program is not thread safe and cause run time error in debug mode
- References:
- This program is not thread safe and cause run time error in debug mode
- From: Tony Johansson
- Re: This program is not thread safe and cause run time error in debug mode
- From: Sergey Zyuzin
- This program is not thread safe and cause run time error in debug mode
- Prev by Date: Re: Sorting
- Next by Date: Re: Sorting
- Previous by thread: Re: This program is not thread safe and cause run time error in debug mode
- Next by thread: Re: This program is not thread safe and cause run time error in debug mode
- Index(es):