Friday, November 18, 2005
ThreadStaticAttribute
Static methods usually do not store state in class level variables for it would be shared by all other static methods too. Unless marked ‘volatile’ two threads executing two different static methods on the same class could step on each other while assigning / reading from the variable. Also, they get to share the copy of the state. Now you could store state from a static method into “ThreadStatic” variables that only the same executing thread could see. There’s a side effect though: If you happen to use a ThreadPool. ThreadPool threads could be reused leading to state being visible when it isn’t supposed to be. Well, you could always re-initialize before exiting. The following example demonstrates that.
using System;
using System.Threading;
public class TestThreadStatic
{
int completed = 0;
public static void Main(string [] args)
{
TestThreadStatic tts = new TestThreadStatic();
tts.StartTesting();
while(tts.completed < 5)
{
Thread.Sleep(1000);
}
}
public void StartTesting()
{
Console.WriteLine("Initial value of ticks at " +
" the beginning: {0}", ticks);
for(int i = 0; i < 5; i++)
{
Console.WriteLine("Assigning work item {0}", i);
ThreadPool.QueueUserWorkItem(ExecutedOnAThread, i);
}
}
[ThreadStatic]
private static long ticks;
public void ExecutedOnAThread(object state)
{
string hashCode = Thread.CurrentThread.GetHashCode().ToString();
//Initialize only once
switch(ticks)
{
case 0:
Console.WriteLine("[{0}] A New Thread", hashCode);
ticks = -2;
break;
case -1:
Console.WriteLine("[{0}] Thread reused", hashCode);
break;
default: // if ticks is -2
Console.WriteLine("[{0}] A supposedly new " +
"thread is able to see " +
"the old value {1}",
hashCode,
ticks);
break;
}
Console.WriteLine("[{0}] Ticks at starting: {1}"
, hashCode, ticks);
ticks = DateTime.Now.Ticks;
Console.WriteLine("[{0}] Ticks at End: {1}", hashCode, ticks);
ticks = -1;
//If sleep is reduced some of the threads would be reused
Thread.Sleep(5000);
completed++;
}
}
Remember, the variable must be declared static.
Results (if running with a 5 second delay):
Initial value of ticks at the beginning: 0
Assigning work item 0
Assigning work item 1
Assigning work item 2
Assigning work item 3
Assigning work item 4
[3] A New Thread
[3] Ticks at starting: -2
[3] Ticks at End: 632691576162343750
[4] A New Thread
[4] Ticks at starting: -2
[4] Ticks at End: 632691576171406250
[5] A New Thread
[5] Ticks at starting: -2
[5] Ticks at End: 632691576176406250
[6] A New Thread
[6] Ticks at starting: -2
[6] Ticks at End: 632691576181406250
[7] A New Thread
[7] Ticks at starting: -2
[7] Ticks at End: 632691576186406250
If the delay is made 1 second:
Initial value of ticks at the beginning: 0
Assigning work item 0
Assigning work item 1
Assigning work item 2
Assigning work item 3
Assigning work item 4
[3] A New Thread
[3] Ticks at starting: -2
[3] Ticks at End: 632691595203906250
[3] Thread reused
[3] Ticks at starting: -1
[3] Ticks at End: 632691595213906250
[4] A New Thread
[4] Ticks at starting: -2
[4] Ticks at End: 632691595213906250
[5] A New Thread
[5] Ticks at starting: -2
[5] Ticks at End: 632691595218906250
[3] Thread reused
[3] Ticks at starting: -1
[3] Ticks at End: 632691595223906250
Thursday, November 17, 2005
Software as a Service
The Machines & Us
Saturday, October 16, 2004
Finding the angle between two clock hands
I had come across an URL couple of days back: http://www.karrels.org/Ed/ACM/ec97/prob_2.html where this problem of finding the angle between two clock hands was mentioned. I wrote the following C# code yesterday. This seems to work (at least for the test inputs posted on the page). Do let me know if there's a bug.
1 using System;
2
3 public class ClockProblem
4 {
5 #region Public Methods
6
7 public static void Main(string[] args)
8 {
9 if (args.Length != 1)
10 {
11 Console.WriteLine("Usage: ClockProblem 12:00");
12 return;
13 }
14 string[] time = args[0].Split(':');
15 var hr = Convert.ToInt32(time[0]);
16 var min = Convert.ToInt32(time[1]);
17 var clock = new ClockProblem();
18 Console.WriteLine(
19 "Angle between two hands at hour {0} min {1} is {2}",
20 time[0],
21 time[1],
22 clock.FindAngleBetweenHands(hr, min)
23 );
24 }
25
26 public float FindAngleBetweenHands(int hour, int minute)
27 {
28 float minuteHandAngle, hourHandAngle, angle;
29
30 //If it's 12 hour consider it 0 if(hour == 12) hour = 0;
31 //Whole clock face has 360 degrees and hence for each minute,
32 //the minute hand must move 6 degrees in clockwise direction
33 minuteHandAngle = minute * 6;
34
35 //A hour hand moves 30 degrees in an hour.
36 //Hence (hour * 30) gives us the number of degrees it moves.
37 //Also, the hour hand must move 0-30 degrees in accordance with
38 //the number of minutes the minute hand is showing.
39 //the hour hand moves 0.5f degrees per minute.
40 //Adjust hour angle accordingly.
41 hourHandAngle = (hour * 30) + (minute * 0.5f) ;
42 angle = Math.Abs(hourHandAngle - minuteHandAngle);
43
44 //The degrees must always be within 180 degrees meaning
45 //3:00 & 9:00 PM both show 90 degrees. if(angle > 180)
46 angle = 360 - angle;
47 return angle;
48 }
49
50 #endregion
51 }