[Mono-devel-list] Re: Threading model

Paul F. Johnson paul at all-the-johnsons.co.uk
Fri Aug 5 07:59:21 EDT 2005


Hi,

> > I think I've found a problem between Mono and the latest kernel and I'm
> > trying to find what it is. I've been advised to look at threading as a
> > potential cause.
> 
> What kind of problems?

Nothing major - just being able to have full root access as a standard
user after runaway threads...

> > Does the threading system change depending on the OS (for instance,
> > Linux and MacOS would use POSIX, Win32 uses Win32) or does it have it's
> > own threading model which is completely cross platform?
> 
> The managed threading model is the same. However, testing the code
> on several platform usually exposes your own threading bugs,
> so please post some code.

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++;
    accessCountBox.Text = accessCount.ToString();
  }

  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);
    watch.Text = "Begin watching";
    watch.Location = new Point(210, 10);

    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)
    {
      t1.Text = (++count1).ToString();
      t2.Text = (++count2).ToString();
      Thread.Sleep(500);
    }
  }

  public void synchTest()
  {
    del();
    if (count1 != count2)
      lbl.Text = "Unsynched";
  }
}

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);
    }
  }
}

Compile, run, click the first, the second, the first. Locks the desktop,
but allows keyboard input (though you can't see what you're typing).

kernel-2.6.12-1.1448_FC5

TTFN

Paul
-- 
"Some people will do anything for a woman in uniform" - The Doctor -
Unregenerate (Big Finish audio)




More information about the Mono-devel-list mailing list