I was recently asked a thread safety question in a c# interview. I didn't get it quite right. I'm am trying to understand it now. Here's the question...
Given a basic Order class...
using System;
namespace OrderThreadTest
{
public class Order
{
public TimeSpan CancelTime;
public int Id;
}
}
Given a simple schedule class stub however I have implemented it to test at home...
using System;
using System.Threading;
namespace OrderThreadTest
{
public class Scheduler : IDisposable
{
private Timer _timer;
public IDisposable Schedule(Order order, Action action)
{
var current = DateTime.Now;
var timeToGo = order.CancelTime - current.TimeOfDay;
_timer = new Timer(x => { action(); }, null, timeToGo, Timeout.InfiniteTimeSpan);
return this;
}
public void Dispose()
{
}
}
}
How do you ensure that the Cancel method in the worker class is thread safe? My answer is the commented out pieces
using System;
namespace OrderThreadTest
{
public class Answer
{
private readonly Scheduler _scheduler;
private object _myLock = new object();
private Order _order;
public Answer(Scheduler scheduler)
{
_scheduler = scheduler;
}
public void Cancel(Order order)
{
// lock (_myLock)
// {
// _order = order;
// var result =
_scheduler.Schedule(order, () =>
{
//if (order.Equals(_order))
//{
Console.WriteLine("Canceled: " + order.Id);
order = null;
//}
});
// }
}
}
}
My first question in understanding this is how can I cause an example of a second thread setting the passed in Order and changing a earlier timer? For example cause a thread data clash.
I have tried like this but it always seems to run as expected...
using System;
namespace OrderThreadTest
{
internal class Program
{
private static void Main(string[] args)
{
var a1 = new Answer(new Scheduler());
var o = new Order
{Id = 1, CancelTime = new TimeSpan(DateTime.Now.Hour, DateTime.Now.Minute, DateTime.Now.Second + 5)};
a1.Cancel(o);
a1.Cancel(o);
Console.ReadLine();
}
}
}
How do I repro the problem that I am meant to solve here?