[Mono-bugs] [Bug 75729][Nor] New - Thread lock causing problems
with the X layer interface
bugzilla-daemon at bugzilla.ximian.com
bugzilla-daemon at bugzilla.ximian.com
Sat Aug 6 05:11:04 EDT 2005
Please do not reply to this email- if you want to comment on the bug, go to the
URL shown below and enter your comments there.
Changed by paul at all-the-johnsons.co.uk.
http://bugzilla.ximian.com/show_bug.cgi?id=75729
--- shadow/75729 2005-08-06 05:11:04.000000000 -0400
+++ shadow/75729.tmp.802 2005-08-06 05:11:04.000000000 -0400
@@ -0,0 +1,271 @@
+Bug#: 75729
+Product: Mono: Class Libraries
+Version: unspecified
+OS:
+OS Details: FC4
+Status: NEW
+Resolution:
+Severity:
+Priority: Normal
+Component: Windows.Forms
+AssignedTo: mono-bugs at ximian.com
+ReportedBy: paul at all-the-johnsons.co.uk
+QAContact: mono-bugs at ximian.com
+TargetMilestone: ---
+URL:
+Cc:
+Summary: Thread lock causing problems with the X layer interface
+
+Please fill in this template when reporting a bug, unless you know what you
+are doing.
+Description of Problem:
+The code in the additional information will compile and run, but after 100
+or so threads, causes a stack throwback. It is probably some form of lock
+problem on the threader.
+
+I have no problems having this added as a test case :-)
+
+Steps to reproduce the problem:
+1. Compile the code and run. Use an x86 Linux box
+2.
+3.
+
+Actual Results:
+The following stack throwback is given
+
+Unhandled Exception: System.ObjectDisposedException: The object was
+used after being disposed.
+in [0x0002d] System.Threading.WaitHandle:CheckDisposed ()
+in [0x00001] (at mcs/class/corlib/System.Threading/WaitHandle.cs:177)
+System.Threading.WaitHandle:WaitOne ()
+in [0x0000e] (at
+mcs/class/Managed.Windows.Forms/System.Windows.Forms/AsyncMethodResult.cs:78)
+System.Windows.Forms.AsyncMethodResult:Complete (System.Object result)
+in [0x00062] (at
+mcs/class/Managed.Windows.Forms/System.Windows.Forms/XplatUIDriver.cs:279)
+System.Windows.Forms.XplatUIDriverSupport:ExecuteClientMessage
+(GCHandle gchandle)
+in [0x00a8c] (at
+mcs/class/Managed.Windows.Forms/System.Windows.Forms/XplatUIX11.cs:2536)
+System.Windows.Forms.XplatUIX11:GetMessage (System.Windows.Forms.MSG
+msg, IntPtr handle, Int32 wFilterMin, Int32 wFilterMax)
+in [0x00009] (at
+mcs/class/Managed.Windows.Forms/System.Windows.Forms/XplatUI.cs:440)
+System.Windows.Forms.XplatUI:GetMessage (System.Windows.Forms.MSG msg,
+IntPtr hWnd, Int32 wFilterMin, Int32 wFilterMax)
+in [0x0012e] (at
+mcs/class/Managed.Windows.Forms/System.Windows.Forms/Application.cs:365)
+System.Windows.Forms.Application:Run ()
+in [0x0004a] (at
+mcs/class/Managed.Windows.Forms/System.Windows.Forms/Application.cs:388)
+System.Windows.Forms.Application:Run
+(System.Windows.Forms.ApplicationContext context)
+in [0x0000c] (at
+mcs/class/Managed.Windows.Forms/System.Windows.Forms/Application.cs:379)
+System.Windows.Forms.Application:Run (System.Windows.Forms.Form
+mainForm)
+in <0x000b8> Sharing1:Main (System.String[] args)
+
+Expected Results:
+The program should run
+
+How often does this happen?
+Always
+
+Additional Information:
+
+Source listing
+
+using System;
+using System.Threading;
+using System.Windows.Forms;
+using System.Drawing;
+
+public class Sharing1 : Form
+{
+ private TextBox accessCountBox = new TextBox();
+ private Button start = new Button();
+ private Button watch = new Button();
+ private int accessCount = 0;
+
+ public void incrementAccess()
+ {
+ accessCount++;
+ UpdateAccess();
+ }
+
+ public void UpdateAccess()
+ {
+ if (!accessCountBox.InvokeRequired)
+ accessCountBox.Text = accessCount.ToString();
+ else
+ accessCountBox.BeginInvoke(new MethodInvoker(UpdateAccess));
+ }
+
+ private int numCounters = 12;
+ private int numWatchers = 15;
+ private TwoCounter[] s;
+
+ public Sharing1()
+ {
+ ClientSize = new Size(450, 480);
+ Panel p = new Panel();
+ p.Size = new Size(400, 50);
+ start.Click += new EventHandler(StartAllThreads);
+ watch.Click += new EventHandler(StartAllWatchers);
+
+ accessCountBox.Text = "0";
+ accessCountBox.Location = new Point(10, 10);
+ start.Text = "Start threads";
+ start.Location = new Point(110, 10);
+ start.Width = 80;
+ watch.Text = "Begin watching";
+ watch.Location = new Point(210, 10);
+ watch.Width = 180;
+
+ p.Controls.Add(start);
+ p.Controls.Add(watch);
+ p.Controls.Add(accessCountBox);
+
+ s = new TwoCounter[numCounters];
+ for (int i = 0; i < s.Length; i++)
+ {
+ s[i] = new TwoCounter(new TwoCounter.IncrementAccess(incrementAccess));
+ s[i].Location = new Point(10, 50 + s[i].Height * i);
+ Controls.Add(s[i]);
+ }
+
+ this.Closed += new EventHandler(StopAllThreads);
+ Controls.Add(p);
+ }
+
+ public void StartAllThreads(object sender, EventArgs ea)
+ {
+ for (int i = 0; i < s.Length; i++)
+ s[i].Start();
+ }
+
+ public void StopAllThreads(object sender, EventArgs ea)
+ {
+ for (int i = 0; i < s.Length; i++)
+ if (s[i] != null)
+ s[i].Stop();
+ }
+
+ public void StartAllWatchers(object sender, EventArgs ea)
+ {
+ for (int i = 0; i < numWatchers; i++)
+ new Watcher(s);
+ }
+
+ public static void Main(string [] args)
+ {
+ Sharing1 app = new Sharing1();
+ if (args.Length > 0)
+ {
+ app.numCounters = SByte.Parse(args[0]);
+ if (args.Length == 2)
+ app.numCounters = SByte.Parse(args[1]);
+ }
+ Application.Run(app);
+ }
+}
+
+class TwoCounter : Panel
+{
+ private bool started = false;
+ private Label t1;
+ private Label t2;
+ private Label lbl;
+ private Thread t;
+
+ private int count1 = 0, count2 = 0;
+ public delegate void IncrementAccess();
+ IncrementAccess del;
+
+ public TwoCounter(IncrementAccess del)
+ {
+ this.del = del;
+ this.Size = new Size(350, 30);
+ this.BorderStyle = BorderStyle.Fixed3D;
+ t1 = new Label();
+ t1.Location = new Point(10, 10);
+ t2 = new Label();
+ t2.Location = new Point(110, 10);
+ lbl = new Label();
+ lbl.Location = new Point(210, 10);
+ lbl.Text = "Count1 == Count2";
+ Controls.AddRange(new Control[] {t1, t2, lbl} );
+
+ t = new Thread(new ThreadStart(run));
+ }
+
+ public void Start()
+ {
+ if (!started)
+ {
+ started = true;
+ t.Start();
+ }
+ }
+
+ public void Stop()
+ {
+ t.Abort();
+ }
+
+ public void run()
+ {
+ while(true)
+ {
+ UpdateLabels();
+ Thread.Sleep(500);
+ }
+ }
+
+ public void synchTest()
+ {
+ del();
+ if (count1 != count2)
+ UpdateSynch();
+ }
+
+ private void UpdateLabels()
+ {
+ if (!t1.InvokeRequired) {
+ t1.Text = (++count1).ToString();
+ t2.Text = (++count2).ToString();
+ } else // Will be queued for execution in the UI Thread
+ t1.BeginInvoke(new MethodInvoker(UpdateLabels));
+ }
+
+ private void UpdateSynch()
+ {
+ if (!lbl.InvokeRequired)
+ lbl.Text = "Unsynched";
+ else // Will be queued for execution in the UI Thread
+ lbl.BeginInvoke(new MethodInvoker(UpdateSynch));
+ }
+
+}
+
+class Watcher
+{
+ TwoCounter[] s;
+
+ public Watcher(TwoCounter[] s)
+ {
+ this.s = s;
+ new Thread(new ThreadStart(run)).Start();
+ }
+
+ public void run()
+ {
+ while(true)
+ {
+ for(int i = 0; i < s.Length; i++)
+ s[i].synchTest();
+ Thread.Sleep(500);
+ }
+ }
+}
More information about the mono-bugs
mailing list