Why no cross-threading problems with DispatcherTimer?

R

RayLopez99

How come there are no cross-threading issues in the program below,
involving two WPF/Silverlight timers from the class DispatcherTimer?

As can be seen below, a single class, called SharedClass1
mySharedClass; , is shared by both the “Tick” event handlers from each
timer, and inside these methods you can manipulate the public
properties of the class as you please. In more elaborate versions of
this program (not shown) I have added and deleted elements from a
list, dictionary, etc, with no problems involving cross-threading.
Also note you can output to a XAML Textblock below, with no runtime
exceptions. In a more elaborate version of this program (not shown
here) I have artificially created a “race” violation, in that one
timer (which runs faster than the other) has to wait for the other
timer to ‘catch up’, or the data will be off and/or wrong, but this
has nothing to do with cross-threading. That is a problem fixed by a
lock, etc.

I was expecting to get a runtime exception when either outputting to
the textblock from within the timer or when accessing the contents of
the properties of the class mySharedClass, which are changed/
manipulated by both timers. Why did I not? Perhaps (I’m guessing) in
the DispatcherTimer class they somehow get copies of the objects being
manipulated rather than the actual objects, or something like that.

RL


using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Threading;
using System.Diagnostics;

namespace TimerThreadDemo1
{

/// <summary>

/// OUTPUT:
/*

Int2 : 1,Property2+1: 1
Int2 : 2,Property2+1: 2
Int1 : 1,Property1: 1
Int2 : 3,Property2+1: 4
Int2 : 4,Property2+1: 5
Int1 : 2,Property1: 2
Int2 : 5,Property2+1: 7
Int1 : 3,Property1: 3
Int2 : 6,Property2+1: 9
Int2 : 7,Property2+1: 10
Int1 : 4,Property1: 4
Int2 : 8,Property2+1: 12
Int2 : 9,Property2+1: 13
Int1 : 5,Property1: 5
Int2 : 10,Property2+1: 15
Int2 : 11,Property2+1: 16
Int1 : 6,Property1: 6
Int2 : 12,Property2+1: 18
Int2 : 13,Property2+1: 19
Int1 : 7,Property1: 7
Int2 : 14,Property2+1: 21
Int2 : 15,Property2+1: 22
*
*
* */
/// </summary>

public partial class MainPage : UserControl
{
DispatcherTimer myDispatchTimer1;
DispatcherTimer myDispatchTimer2;
int count1;
int count2;
SharedClass1 mySharedClass;

public MainPage()
{
InitializeComponent();
myDispatchTimer1 = new DispatcherTimer();
mySharedClass = new SharedClass1(1, 100);

myDispatchTimer1.Interval = new TimeSpan(0, 0, 0, 0,
200); //0.2 seconds = interval
myDispatchTimer1.Tick += new
EventHandler(myDispatchTimer1_Tick);
count1 = 0;
count2 = 0;

myDispatchTimer2 = new DispatcherTimer();
myDispatchTimer2.Interval = new TimeSpan(0, 0, 0, 0,
100); //100 ms = interval
myDispatchTimer2.Tick += new
EventHandler(myDispatchTimer2_Tick);

}

void myDispatchTimer1_Tick(object sender, EventArgs e)
{
count1++;
mySharedClass.Property1 = count1;
myTextBlock1.Text = "Int1 : " + count1.ToString() + "," +
"Property1: " + mySharedClass.Property1.ToString();
Debug.WriteLine("Int1 : " + count1.ToString() + "," +
"Property1: " + mySharedClass.Property1.ToString());

}

void myDispatchTimer2_Tick(object sender, EventArgs e)
{
//try and create conflict with first property here...see
if cross thread issues arise...nope!
count2++;
mySharedClass.Property2 = count2 + count1;
myTextBlock2.Text = "Int2 : " + count2.ToString() + "," +
"Property2+1: " + mySharedClass.Property2.ToString();
Debug.WriteLine("Int2 : " + count2.ToString() + "," +
"Property2+1: " + mySharedClass.Property2.ToString());
}

private void myButton1A_Click(object sender, RoutedEventArgs
e)
{
myDispatchTimer1.Start();
myDispatchTimer2.Start();
}

private void myButton1B_Click(object sender, RoutedEventArgs
e)
{
myDispatchTimer1.Stop();
myDispatchTimer2.Stop();
}


private void myDebugBtn1_Click(object sender, RoutedEventArgs
e)
{
int[] PropertyArrIntsTemp =
mySharedClass.returnProperties();

foreach (int i in PropertyArrIntsTemp)
{
Debug.WriteLine("Properties are: " + i.ToString());
}
}
}
}

//

using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace TimerThreadDemo1
{
public class SharedClass1
{
int _Property1;
int _Property2;

public int Property1
{
get { return _Property1; }
set { _Property1 = value; }
}

public int Property2
{
get { return _Property2; }
set { _Property2 = value; }
}

public SharedClass1() { }

public SharedClass1(int i, int j)
{
Property1 = i;
Property2 = j;
}


public int[] returnProperties()
{
int[] PropertyArrInts = new int[2];
PropertyArrInts[0] = Property1;
PropertyArrInts[1] = Property2;

return PropertyArrInts;

}

}
}
 
R

RayLopez99

        void myDispatchTimer2_Tick(object sender, EventArgs e)
        {
            //try and create conflict with first property here...see
if cross thread issues arise...nope!
            count2++;
            mySharedClass.Property2 = count2 + count1;
            myTextBlock2.Text = "Int2 : " + count2.ToString() + "," +



Just to be clear, there are no cross-threading issues (runtime
exceptions) even if you change the line in timer2 above
"mySharedClass.Property2 = count2 + count1; " to
"mySharedClass.Property2 = count2 + mySharedClass.Property1", which is
counterintutive since Property1 is being changed in timer 1.

RL
 
R

RayLopez99

I just realized why there are no cross-threading issues:
DispatcherTimer is a single-threaded timer! No matter how many timers
you have in your program, if they are DispatcherTimer class, they are
single threaded.

Duh!

So you'll never have cross-threading issues. Thus try and use
DispatcherTimer whenever possible, unless you have some serious
computationally heavy problems that need their own timer.

From Chapter 19 of Albahari's book.

RL
 

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