I have a CountDownTimer class that updates a controller that updates the user interface. The problem i have is when i run my unit tests i get a NllReferenceException because the event handlder(Tick) is never initialized always null. What is the best possible solution to this problem? Or should i go about it differently. Thanks
public class CountDownTimer : ICountDownTimer
{
private int seconds; // Time in seconds
private int reSetValue; // Time in seconds
private System.Windows.Forms.Timer timer1;
public event TickHandler Tick;
public EventArgs e = null;
public delegate void TickHandler(CountDownTimer m, EventArgs e, int seconds);
public CountDownTimer(int seconds)
{
this.seconds = seconds;
reSetValue = seconds;
timer1 = new System.Windows.Forms.Timer();
timer1.Tick += new EventHandler(timer1_Tick); // Add Handler(timer1_Tick)
timer1.Interval = 1000; // 1 second
}
private void timer1_Tick(object sender, EventArgs e)
{
CallTickHandler();
if (getSeconds() == 0) // Stop Timer at 0
{
timer1.Stop(); // Stop timer
}
else
{
if (getSeconds() % 60 == 0 || getSeconds() >= 1 && getSeconds() <= 10)
{
CallTickHandler();
}
}
seconds--; // Decrement seconds
}
public void StartTimer()
{
timer1.Start();
}
public void StopTimer()
{
timer1.Stop();
}
public void ResetTimer()
{
timer1.Stop();
seconds = reSetValue;
CallTickHandler();
}
public void SetTimer(int seconds)
{
timer1.Stop();
this.seconds = getSeconds();
reSetValue = getSeconds();
CallTickHandler();
}
internal void CallTickHandler()
{
Tick(this, e, getSeconds());
}
public Boolean isEnabled()
{
return timer1.Enabled;
}
public int getSeconds()
{
return seconds;
}
}
public class Controller : ApplicationContext
{
//Store a reference to the UI
internal frmMain MainUI { get; set; }
private int seconds = 300;
CountDownTimer timer;
public Controller()
{
MainUI = new frmMain(this);
//We can do any necessary checks or changes to the MainUI here before it becomes visible
MainUI.Show();
timer = new CountDownTimer(seconds);
SubscribeToTickListener(timer);
TickUpdate(seconds);
}
internal void TickUpdate(string seconds)
{
MainUI.lblTimer.Text = ("" + Convert.ToInt32(seconds) / 60).PadLeft(2, '0') + "m:" + ("" + Convert.ToInt32(seconds) % 60).PadLeft(2, '0') + "s";
}
internal void TickUpdate(int seconds)
{
MainUI.lblTimer.Text = ("" + seconds / 60).PadLeft(2, '0') + "m:" + ("" + seconds % 60).PadLeft(2, '0') + "s";
if (seconds <= 10)
{
//ss.Speak(seconds.ToString());
}
else
{
//ss.Speak((seconds / 60).ToString() + " minute warning");
}
}
internal void StartTimer()
{
timer.StartTimer();
}
internal void ResetTimer()
{
timer.ResetTimer();
}
internal void StopTimer()
{
timer.StopTimer();
}
internal void SetTimer(int seconds)
{
timer.SetTimer(seconds);
}
public void SubscribeToTickListener(CountDownTimer cdt)
{
cdt.Tick += new CountDownTimer.TickHandler(TickMsgRecieved);
}
public void TickMsgRecieved(CountDownTimer cdt, EventArgs e, int seconds)
{
TickUpdate(seconds);
TickUpdate(seconds.ToString());
}
}
public class CountDownTimerTests
{
private CountDownTimer t = new CountDownTimer(300);
[TestMethod()]
public void CountDownTimerTest()
{
CountDownTimer t = new CountDownTimer(300);
}
[TestMethod()]
public void StartTimerTest()
{
//CountDownTimer t = new CountDownTimer(300);
t.StartTimer();
Boolean expected = t.isEnabled();
Boolean actual = true;
Assert.AreEqual(expected, actual);
}
[TestMethod()]
public void StopTimerTest()
{
//CountDownTimer t = new CountDownTimer(300);
t.StartTimer();
t.StopTimer();
Boolean expected = t.isEnabled();
Boolean actual = false;
Assert.AreEqual(expected, actual);
}
[TestMethod()]
public void ResetTimerTest()
{
int expected = t.getSeconds();
t.ResetTimer();
int actual = t.getSeconds();
Assert.AreEqual(expected, actual);
}
[TestMethod()]
public void SetTimerTest()
{
int expected = t.getSeconds();
t.SetTimer(120);
int actual = t.getSeconds();
Assert.AreEqual(expected, actual);
}
}
In this case you can probably use a mock implementation of the event. I would add the following mock event to your test class to simulate a consumer of the CountDownTimer class.
[TestInitialize]
public void TestSetup()
{
t.Tick += new CountDownTimer.TickHandler(MockTickEvent);
}
[TestCleanup]
public void TestCleanup()
{
t.Tick -= MockTickEvent;
}
void MockTickEvent(CountDownTimer m, EventArgs e, int seconds)
{
///you may need to add further test code here to fully cover your code
return;
}
Related
I'm using SharpDx and X-input to get my Xbox Controller's input but I'm having trouble finding to simulate the right arrow key when I move my right joystick right. This is what I got so far. My issue is when I move the stick to the right it presses the arrow key more than once so I tried to set up a thread.sleep to make it press every second but did not work. Kinda running out of ideas and would really appreciate some help.
public class XboxController
{
private const int V = 2_000;
private Controller _controller;
private IMouseSimulator _mouseSimulator;
private IKeyboardSimulator _keyboardSimulator;
private Timer _timer;
private bool _wasADown;
public int deadband = 2500;
private const int RefreshRate = 60;
public XboxController()
{
_controller = new SharpDX.XInput.Controller(UserIndex.One);
_mouseSimulator = new InputSimulator().Mouse;
_keyboardSimulator = new InputSimulator().Keyboard;
_timer = new Timer(obj => Update());
DispatcherTimer timer = new DispatcherTimer();
timer.Interval = TimeSpan.FromSeconds(1);
timer.Tick += timer_Tick;
timer.Start();
}
private void timer_Tick(object sender, EventArgs e)
{
}
public void Start()
{
_timer.Change(0, 1000 / RefreshRate);
}
private void Update()
{
_controller.GetState(out var state);
Movement(state);
Scroll(state);
LeftButton(state);
RightButton(state);
Stick(state);
}
private void RightButton(State state)
{
if (state.Gamepad.Buttons == GamepadButtonFlags.B)
{
_keyboardSimulator.KeyPress(WindowsInput.Native.VirtualKeyCode.BACK);
Thread.Sleep(1000);
}
}
private void LeftButton(State state)
{
var isADown = state.Gamepad.Buttons.HasFlag(GamepadButtonFlags.A);
if (isADown && !_wasADown) _mouseSimulator.LeftButtonDown();
if (!isADown && _wasADown) _mouseSimulator.LeftButtonUp();
_wasADown = isADown;
}
private void Scroll(State state)
{
var x = state.Gamepad.RightThumbX / 10000;
var y = state.Gamepad.RightThumbY / 10000;
_mouseSimulator.HorizontalScroll(x);
_mouseSimulator.VerticalScroll(y);
}
private void Movement(State state)
{
var x = state.Gamepad.LeftThumbX / 2500;
var y = state.Gamepad.LeftThumbY / 2500;
_mouseSimulator.MoveMouseBy(x, -y);
}
private void Stick(State state)
{
while ((state.Gamepad.RightThumbX) > 0)
{
Thread.Sleep(1000);
_keyboardSimulator.KeyPress(WindowsInput.Native.VirtualKeyCode.RIGHT);
Thread.Sleep(1000);
}
}
}
}
I am trying to implement a timer as per the below code. I want to pass a parameter to the timer event. I have used below anonymous function approach.
However this would only pass only the first parameter to the OnTimerElapsedEvent. Can someone please advise?
class Program
{
static void Main(string[] args)
{
ClassA obj = new ClassA();
Console.WriteLine("Start" + " " + System.DateTime.Now);
obj.SampleMethod("hello", 3000);
Thread.Sleep(4000);
obj.SampleMethod("world", 6000);
Console.ReadKey();
}
}
class ClassA
{
private System.Timers.Timer tTimer;
public void SampleMethod(string strParam, int iTimerInterval)
{
if (tTimer == null)
{
tTimer = new System.Timers.Timer();
tTimer.Elapsed += (sender, e) =>
OnTimerElapsedEvent(sender, e, strParam);
}
tTimer.Interval = iTimerInterval;
tTimer.Enabled = true;
tTimer.Start();
}
private void OnTimerElapsedEvent(object source, ElapsedEventArgs e, string strParam)
{
//use strParam value here
Console.WriteLine(strParam + " " + System.DateTime.Now);
if (strParam == "world")
{
tTimer.Stop();
tTimer.Enabled = false;
}
}
}
You can inherit the Timer class to provide a parameter in the constructor like below. Or you can inherit the Timer class and provide a property:
[TestClass]
public class TimerTester
{
[TestMethod]
public void TestYourTimer()
{
var timer1 = new TimerWithParameter("param1");
timer1.Interval = 1000;
timer1.ElapsedEvent += Timer_ElapsedEvent;
timer1.Start();
var timer2 = new TimerWithParameter("param2");
timer2.Interval = 1300;
timer2.ElapsedEvent += Timer_ElapsedEvent;
timer2.Start();
Thread.Sleep(5000);
}
private void Timer_ElapsedEvent(object source, ElapsedEventArgs e, string strParam)
{
Debug.WriteLine(strParam);
}
}
public delegate void ElapsedWithParameterDelegate(object source, ElapsedEventArgs e, string strParam);
public class TimerWithParameter:Timer
{
private readonly string _strParam;
public event ElapsedWithParameterDelegate ElapsedEvent;
public TimerWithParameter(string strParam)
{
_strParam = strParam;
this.Elapsed += TimerWithParameter_Elapsed;
}
private void TimerWithParameter_Elapsed(object sender, ElapsedEventArgs e)
{
ElapsedEvent?.Invoke(this, e, _strParam);
}
}
I have WinForms App where I am using the code in this following Post to check the InActivity Status of my app (Please see the accepted answer in the post). InActivity In WinForms. Once the app reaches inactivity its stopping the inactivity monitor. But then I want to restart the time once the user logs in.
So I have a notification mechanism when the user logs in and I am calling the start timer method again. I get the Started Monitor Message but the app never tracks inactivity and I don't get Timer reporting app is InACTIVE message at all. Please help.
public static System.Windows.Forms.Timer IdleTimer =null;
static int MilliSeconds = 60000;
static void Main(string[] args)
{
f = new GeneStudyForm(true, arguments.SystemTimeOutFolder, arguments.SystemTimeOutFile, StartInActivityMonitor);
int x = StartInActivityMonitor();
}
public static void StartInActivityMonitor()
{
IdleTimer = new Timer();
LeaveIdleMessageFilter limf = new LeaveIdleMessageFilter();
Application.AddMessageFilter(limf);
IdleTimer.Interval = MilliSeconds; //One minute; change as needed
Application.Idle += new EventHandler(Application_Idle);
if (IdleTimer != null)
{
MessageBox.Show(IdleTimer.Interval.ToString());
}
IdleTimer.Tick += TimeDone;
IdleTimer.Tag = InActivityTimer.Started;
MessageBox.Show("starting");
IdleTimer.Start();
}
static private void Application_Idle(object sender, EventArgs e)
{
if (!IdleTimer.Enabled) // not yet idling?
IdleTimer.Start();
}
static private void TimeDone(object sender, EventArgs e)
{
try
{
MessageBox.Show("Stopped");
IdleTimer.Stop(); // not really necessary
f.MonitorDirectory();
f.UpdateInActivityStatus();
IdleTimer.Tick -= TimeDone;
Application.Idle -= new EventHandler(Application_Idle);
}
catch(Exception ex)
{
MessageBox.Show(ex.InnerException + ex.Data.ToString());
}
}
Here is my GeneStudyForm
public partial class GeneStudyForm
{
GeneStudySystemTimeOutIO GeneStudyIO;
Func<int> StartTimer;
//Passing the StartInActivityMonitor Method as Func Delegate
public GeneStudyForm(bool isStandalone, string TimeOutFolder, string TimeOutFile, System.Func<int> MyMethod)
{
GeneStudyIO = GeneStudySystemTimeOutIO.GetInstance(TimeOutFolder, TimeOutFile);
UpdateActivityStatus(AppName.GeneStudyStatus, ActivityStatus.Active);
this.StartTimer = MyMethod;
}
public void UpdateActivityStatus(AppName name, ActivityStatus status)
{
if (GeneStudyIO != null)
{
GeneStudyIO.WriteToFile(name, status);
}
}
public void MonitorDirectory()
{
FileSystemWatcher fileSystemWatcher = new FileSystemWatcher(GeneStudyIO.GetDriectory());
fileSystemWatcher.NotifyFilter = NotifyFilters.LastWrite;
fileSystemWatcher.Filter = "*.json";
fileSystemWatcher.Changed += FileSystemWatcher_Changed;
fileSystemWatcher.EnableRaisingEvents = true;
}
public void UnRegister(FileSystemWatcher fileSystemWatcher)
{
fileSystemWatcher.Changed -= FileSystemWatcher_Changed;
}
// I am writing the inactive status to a file. So this event will fill
private void FileSystemWatcher_Changed(object sender, FileSystemEventArgs e)
{
try
{
var root = GeneStudyIO.GetDesrializedJson();
if (root != null && root.AllApplications != null)
{
var item = root.AllApplications.Any(x => x.Status == ActivityStatus.Active.ToString());
if (!item)
{
if (InActivecount == 0)
{
GeneStudyAndApplicationCommon.TimeStatus = InActivityTimer.Ended;
MessageBox.Show("I am hiding");
this.Hide();
InActivecount++;
}
}
else
{
if (GeneStudyAndApplicationCommon.TimeStatus == InActivityTimer.Ended)
{
MessageBox.Show("I am showing");
this.Show();
UnRegister(sender as FileSystemWatcher);
UpdateActivityStatus(AppName.GeneStudyStatus, ActivityStatus.Active);
MessageBox.Show("Updated Status");
if (StartTimer != null)
{
MessageBox.Show("Starting Timer again");
if (StartTimer() == -1)
{
MessageBox.Show("Couldn't start timer");
}
}
}
}
}
}
catch (Exception ex)
{
SystemDebugLogLogger.LogException(ex);
}
}
}
This soulution is quite different from what I have posted. But I could solve my problem with this. But I want to post it if it helps someone. Here is the post I am following Last User Input
I created a class called IdleCheck where I am getting LastUserInput as follows
public static class IdleCheck
{
[StructLayout(LayoutKind.Sequential)]
private struct LASTINPUTINFO
{
[MarshalAs(UnmanagedType.U4)]
public int cbSize;
[MarshalAs(UnmanagedType.U4)]
public int dwTime;
}
[DllImport("user32.dll")]
private static extern bool GetLastInputInfo(ref LASTINPUTINFO x);
public static int GetLastInputTime()
{
var inf = new LASTINPUTINFO();
inf.cbSize = Marshal.SizeOf(inf);
inf.dwTime = 0;
return (GetLastInputInfo(ref inf)) ? Environment.TickCount - inf.dwTime : 0;
}
}
Next in the actual Form this is my code. I am using a simple yes no message box to see if the timer can be stopped and recalled again when needed. You can apply your own locking mechanism.
I want the app to time out if it is InActive for 20 seconds. Change it as needed.
public partial class Form1 : Form
{
Timer timer;
const int TIMEOUT_DONE = 20000;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
Reset();
}
void timer_Tick(object sender, EventArgs e)
{
//var ms = TIMEOUT_DONE - IdleCheck.GetLastInputTime();
if (IdleCheck.GetLastInputTime() > TIMEOUT_DONE)
{
DialogResult dialogResult = MessageBox.Show("Sure", "Some Title", MessageBoxButtons.YesNo);
if (dialogResult == DialogResult.Yes)
{
Stop();
Reset();
}
}
}
public void Reset()
{
timer = new Timer();
timer.Interval = 10000;
timer.Tick += timer_Tick;
timer.Start();
}
public void Stop()
{
timer.Tick -= timer_Tick;
timer.Stop();
}
}
Timer is working only one time. This service must be work in every 2minutes...
public partial class Service1 : ServiceBase
{
RuleContext entity = new RuleContext();
private int id;
private Timer _timer;
private DateTime _lastRun = DateTime.Now.AddDays(-1);
public Service1()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
OnTimer();
}
public void OnTimer()
{
Timeout.Infinite);
_timer = new Timer();
_timer.Interval = 2 * 60 * 1000;
_timer.Elapsed += new System.Timers.ElapsedEventHandler(timer_Elapsed);
_timer.Enabled = true;
_timer.AutoReset = true;
_timer.Start();
}
private void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
// ignore the time, just compare the date
if (_lastRun.Date <= DateTime.Now.Date)
{
GetRule();
}
}
protected override void OnStop()
{
}
public void GetRule()
{
var query = from ruleset in entity.RuleSets
join rule in entity.Rules on ruleset.Id equals rule.RuleSetId
join schedulerule in entity.Schedules on rule.ScheduleId equals schedulerule.Id
select new
{
Id = ruleset.Id,
daily = schedulerule.Daily,
mountly = schedulerule.Monthly,
dayofMounth = schedulerule.DayOfMonth,
};
foreach (var q in query.ToList())
{
if (q.mountly && q.daily)
{
if (q.dayofMounth == (int)DateTime.Now.Day)
{
UpdateValue(q.Id);
}
}
else if (q.daily)
{
UpdateValue(q.Id);
}
else if (q.mountly)
{
if (q.dayofMounth == (int)DateTime.Now.Day)
{
UpdateValue(q.Id);
}
}
}
}
public void UpdateValue(int id)
{
var ruleSet = entity.RuleSets.First(k => k.Id == id);
ruleSet.RcvByte = 0;
ruleSet.SentByte = 0;
entity.SaveChanges();
}
}
private void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
// ignore the time, just compare the date
if (_lastRun.Date <= DateTime.Now.Date)
{
GetRule();
}
}
Since the AutoReset property is set to true, no need to Stop and Start timer.
_timer.Stop();
this line is causing this problem. Remove it
I have this class
public class ResetClock
{
public delegate void ResetFunc();
private ResetFunc m_ResetFunc;
private event ResetFunc Reseted;
private Timer m_Timer;
public ResetClock(int second)
{
double r = second * 1000;
m_Timer = new Timer(r);
m_Timer.AutoReset = false;
m_Timer.Elapsed += new ElapsedEventHandler(onTimerTick);
Reset();
}
public void SetResetMethod(ResetFunc method)
{
m_ResetFunc = method;
}
public void Terminate()
{
m_Timer.Stop();
m_Timer.Dispose();
m_Timer = null;
}
private void onTimerTick(object sender, ElapsedEventArgs e)
{
if (m_ResetFunc == null)
{
if (Reseted != null) Reseted();
}
else
{
m_ResetFunc();
}
Reset();
}
#region Public
public void Reset()
{
m_Timer.Reset();
}
#endregion
}
internal static class TimerEx{
public static void Reset(this Timer timer){
timer.Stop();
timer.Start();
}
}
My application is showing the reset page when this class reaches the seconds defined in the contractor. when a Reset() method calls, the Timer should reset the it self and begin the timer from 0.
for some reason after the application is running few days the reset event is firing after few seconds and not the number of seconds that i defined in the first application initialization
does anyone have any idea....??? I braking my head through the wall to find the answer..