WPF: Building a Queue in a Thread with Timers - c#

With reference to the Software Project I am currently working on.
I have the below methods that basically move a canvas with a Timer:
DispatcherTimer dt = new DispatcherTimer(); //global
public void Ahead(int pix)
{
var movx = 0;
var movy = 0;
dt.Interval = TimeSpan.FromMilliseconds(5);
dt.Tick += new EventHandler((object sender, EventArgs e) =>
{
if (movx >= pix || movy >= pix)
{
dt.Stop();
return;
}
Bot.Body.RenderTransform = new TranslateTransform(movx++, movy++);
});
dt.Start();
}
public void TurnLeft(double deg)
{
var currAngle = 0;
dt.Interval = TimeSpan.FromMilliseconds(5);
dt.Tick += new EventHandler(delegate(object sender, EventArgs e)
{
if (currAngle <= (deg - (deg * 2)))
{
dt.Stop();
}
Bot.Body.RenderTransform = new RotateTransform(currAngle--, BodyCenter.X, BodyCenter.Y);
});
dt.Start();
}
Now, from another library, these methods are called like such:
public void run()
{
Ahead(200);
TurnLeft(90);
}
Now of course, I want these animations to happen after another, but what is happening is that the dt.Tick event handler of the DispatchTimer is being overwritten when the second method (in this case, TurnLeft(90)) is invoked and thus, only the second method gets executed as it should.
I need to create some sort of queue that will allow me to push and pop methods to that queue so that dt (the DispatchTimer timer) executes them one by one...in the order they are in the 'queue'
Any way I can go about doing this ? Am I on the right track here, or completely off course?

When you call Invoke() or BeginInvoke() on the Dispatcher, the operation will be queued up and run when the thread associated with the Dispatcher is free. So instead of using the Tick event, use the overload of Dispatcher.Invoke that takes a Timespan.

I have fixed this problem by myself. What I did was create a global Queue of type Delegate and instead of executing the methods directly, I add them to this queue.
Then I would have a separate thread in the constructor that will dequeue methods one by one and executing them:
Queue<TimerDelegate> eventQueue = new Queue<TimerDelegate>();
public Vehicle(IVehicle veh, Canvas arena, Dispatcher battleArenaDispatcher)
{
DispatcherTimer actionTimer = new DispatcherTimer() { Interval = TimeSpan.FromMilliseconds(100) };
actionTimer.Tick += new EventHandler(delegate(object sender, EventArgs e)
{
if (IsActionRunning || eventQueue.Count == 0)
{
return;
}
eventQueue.Dequeue().Invoke(new DispatcherTimer() { Interval = TimeSpan.FromMilliseconds(5) });
});
actionTimer.Start();
}
public void TurnRight(double deg)
{
eventQueue.Enqueue((TimerDelegate)delegate(DispatcherTimer dt)
{
IsActionRunning = true;
var currAngle = 0;
dt.Tick += new EventHandler(delegate(object sender, EventArgs e)
{
lock (threadLocker)
{
if (currAngle >= deg)
{
IsActionRunning = false;
dt.Stop();
}
Rotator_Body.Angle++;
currAngle++;
}
});
dt.Start();
});
}

Related

C# Async download with stopwatch but UI is freezing somewhere

Here is some code that I use to download a file and then calculate the time remaining time and kbps. It will then post those results on the form by updating a text box and it has a progress bar. The problem I am having is the UI is freezing and I am thinking it might be how I am using the stopwatch but not sure. Anyone have any input?
/// Downloads the file.
private void Download_Begin()
{
web_client = new System.Net.WebClient();
web_client.DownloadProgressChanged += new DownloadProgressChangedEventHandler(Download_Progress);
web_client.DownloadFileCompleted += new AsyncCompletedEventHandler(Download_Complete);
stop_watch = new System.Diagnostics.Stopwatch();
stop_watch.Start();
try
{
if (Program.Current_Download == "Install_Client.exe")
{
web_client.DownloadFileAsync(new Uri("http://www.website.com/Client/Install_Client.exe"), #"C:\Downloads\Install_Client.exe");
}
else
{
web_client.DownloadFileAsync(new Uri((string.Format("http://www.website.com/{0}", Program.Current_Download))), (string.Format(#"C:\Downloads\{0}", Program.Current_Download)));
}
}
catch(Exception)
{
stop_watch.Stop();
}
Program.Downloading = true;
Download_Success = false;
}
/// -------------------
/// Tracks download progress.
private void Download_Progress(object sender, DownloadProgressChangedEventArgs e)
{
double bs = e.BytesReceived / stop_watch.Elapsed.TotalSeconds;
this.label_rate.Text = string.Format("{0} kb/s", (bs / 1024d).ToString("0.00"));
long bytes_remaining = e.TotalBytesToReceive - e.BytesReceived;
double time_remaining_in_seconds = bytes_remaining / bs;
var remaining_time = TimeSpan.FromSeconds(time_remaining_in_seconds);
string hours = remaining_time.Hours.ToString("00");
if (remaining_time.Hours > 99)
{
hours = remaining_time.Hours.ToString("000");
}
this.time_remaining.Text = string.Format("{0}::{1}::{2} Remaining", hours, remaining_time.Minutes.ToString("00"), remaining_time.Seconds.ToString("00"));
progressBar1.Maximum = (int)e.TotalBytesToReceive / 100;
progressBar1.Value = (int)e.BytesReceived / 100;
if (e.ProgressPercentage == 100)
{
Download_Success = true;
}
}
/// -------------------------
The UI thread could be freezing for various reasons, despite the fact that you are calling the asynchronous download function. One way of preventing the UI to freeze would be to invoke the downloading of the file from different thread than the UI. For instance you can accomplish this with BackgroundWorker and safely modify form's controls via thread safe calls or in short wrapping the code executed in the non-UI thread with BeginInvoke() calls.
private void button1_Click(object sender, EventArgs e)
{
BackgroundWorker worker = new BackgroundWorker();
worker.DoWork += Worker_DoWork;
worker.RunWorkerAsync();
}
private void Worker_DoWork(object sender, DoWorkEventArgs e)
{
Download_Begin();
}
/// Downloads the file.
private void Download_Begin()
{
web_client = new System.Net.WebClient();
web_client.DownloadProgressChanged += new DownloadProgressChangedEventHandler(Download_Progress);
web_client.DownloadFileCompleted += new AsyncCompletedEventHandler(Download_Complete);
stop_watch = new System.Diagnostics.Stopwatch();
stop_watch.Start();
try
{
if (Program.Current_Download == "Install_Client.exe")
{
web_client.DownloadFileAsync(new Uri("http://www.website.com/Client/Install_Client.exe"), #"C:\Downloads\Install_Client.exe");
}
else
{
web_client.DownloadFileAsync(new Uri((string.Format("http://www.website.com/{0}", Program.Current_Download))), (string.Format(#"C:\Downloads\{0}", Program.Current_Download)));
}
}
catch (Exception)
{
stop_watch.Stop();
}
Program.Downloading = true;
Download_Success = false;
}
/// -------------------
/// Tracks download progress.
private void Download_Progress(object sender, DownloadProgressChangedEventArgs e)
{
this.BeginInvoke(new Action(() =>
{
double bs = e.BytesReceived / stop_watch.Elapsed.TotalSeconds;
this.label_rate.Text = string.Format("{0} kb/s", (bs / 1024d).ToString("0.00"));
long bytes_remaining = e.TotalBytesToReceive - e.BytesReceived;
double time_remaining_in_seconds = bytes_remaining / bs;
var remaining_time = TimeSpan.FromSeconds(time_remaining_in_seconds);
string hours = remaining_time.Hours.ToString("00");
if (remaining_time.Hours > 99)
{
hours = remaining_time.Hours.ToString("000");
}
this.time_remaining.Text = string.Format("{0}::{1}::{2} Remaining", hours, remaining_time.Minutes.ToString("00"), remaining_time.Seconds.ToString("00"));
progressBar1.Maximum = (int)e.TotalBytesToReceive / 100;
progressBar1.Value = (int)e.BytesReceived / 100;
if (e.ProgressPercentage == 100)
{
Download_Success = true;
}
}));
}
Some thoughts about your code:
No need to close stopwatch when exceptions happen, stopwatch does not do any work inside, it simply remember current time when you start stopwatch and calculate difference when you access elapsed time.
When you catch all exceptions, there is no need to provide Exception class (i.e. catch instead of catch(Exception)).
Mark download as completed only in DownloadFileCompleted event, not in DownloadProgressChanged, because ProgressPercentage can be 100 even when download is not completed yet.
When working with async code it is always better to initialize status variables (in your case Download_Success and Program.Downloading) before calling async method, not after.
Now about freezes. DownloadProgreesChanged can be fired very often by WebClient, so UI thread can be flooded by update messages. You need to split report progress and update UI code. UI should be updated in timed manner, for example, twice per second. Very rough code sample below:
// Put timer on your form, equivalent to:
// Update_Timer = new System.Windows.Forms.Timer();
// Update_Timer.Interval = 500;
// Update_Timer.Tick += Timer_Tick;
private void Download_Begin()
{
web_client = new System.Net.WebClient();
web_client.DownloadProgressChanged += new DownloadProgressChangedEventHandler(Download_Progress);
web_client.DownloadFileCompleted += new AsyncCompletedEventHandler(Download_Complete);
Program.Downloading = true;
Download_Success = false;
stop_watch = System.Diagnostics.Stopwatch.StartNew();
Update_Timer.Start();
web_client.DownloadFileAsync(new Uri("uri"), "path");
}
private int _Progress;
private void Download_Progress(object sender, DownloadProgressChangedEventArgs e)
{
_Progress = e.ProgressPercentage;
}
private void Download_Complete(object sender, AsyncCompletedEventArgs e)
{
Update_Timer.Stop();
Program.Downloading = false;
Download_Success = true;
}
private void Timer_Tick(object sender, EventArgs e)
{
// Your code to update remaining time and speed
// this.label_rate.Text = ...
// this.time_remaining.Text = ...
progressBar1.Value = _Progress;
}

Thread and new counter

How to correct the code that each newly launched thread use the new counter. At the moment when you start a new thread hangs the old, instead of going on.
Thanks for help.
private void button1_Click(object sender, EventArgs e)
{
thread[counter] = new Thread(goThread);
thread[counter].Start();
counter++;
}
private void goThread()
{
kolejka[counter] = new PictureBox();
kolejka[counter].Location = new Point(325, n - 150);
kolejka[counter].Image = threading.Properties.Resources.car;
kolejka[counter].Size = new Size(20, 37);
this.Invoke((MethodInvoker)delegate
{
this.Controls.Add(kolejka[counter]);
});
for (int i = 0; i < 500; i++)
{
this.Invoke((MethodInvoker)delegate
{
kolejka[counter].Location = new Point(kolejka[counter].Location.X, kolejka[counter].Location.Y - 3);
this.Refresh();
});
Thread.Sleep(50);
}
}
The problem is that you're increasing the counter variable, but it is used within your threads. Don't do that. In your case it is very important to make information local to the thread, because you want each thread to work on "its own" counter. This can be achieved like this:
private class ThreadInfo
{
public PictureBox Picture;
public int Counter;
}
private void button1_Click(object sender, EventArgs e)
{
kolejka[counter] = new PictureBox();
kolejka[counter].Location = new Point(325, n - 150);
kolejka[counter].Image = threading.Properties.Resources.car;
kolejka[counter].Size = new Size(20, 37);
this.Controls.Add(kolejka[counter]);
ThreadInfo info = new ThreadInfo() {
Picture = kolejka[counter],
Counter = counter
};
thread[counter] = new Thread(goThread);
thread[counter].Start(info);
counter++;
}
private void goThread(object state)
{
ThreadInfo info = state as ThreadInfo;
for (int i = 0; i < 500; i++)
{
this.Invoke((MethodInvoker)delegate
{
info.Picture.Location = new Point(info.Picture.Location.X, info.Picture.Location.Y - 3);
this.Refresh();
});
Thread.Sleep(50);
}
}
This does all the initialization stuff in your button event and passes in an instance of an info class. That info class takes all the information the thread needs, but so that it is local to the thread!
Your old thread is not hanging. The problem is in your counter variable. It is shared by you threads. The old thread just continues on the kolejka[counter] of the new thread. I guess that is not what your want.
In the beginning of your goThread method you can do something like:
var item = kolejka[counter];
And then you can use item instead of kolejka[counter]. However this is not thread safe yet either, but a lot better then you have now.
There are several problems with your code.
You use a variable counter without locking in two threads.
Don't use arrays for this, because you don't have the counter value in control.
Don't create controls on other threads than the gui thread.
For this purpose, you don't need threads. The easiest way is using one timer.
PSEUDO:
List<Car> _myCars = new List<Car>();
private Form1()
{
_timer = new Timer();
_timer.Interval = 50;
_timer.Tick += Timer_Tick;
}
private void Timer_Tick(object sender, EventArgs e)
{
foreach(var car in _myCars.ToArray())
{
car.Location = new Point(car.Location.X, car.Location.Y - 3);
if(car.Location.Y < 0)
_myCars.Remove(car);
}
}
private void button1_Click(object sender, EventArgs e)
{
_myCars.Add(new Car());
}
Follow up on Peter, you could create a copy at the beginning of the thread:
private void button1_Click(object sender, EventArgs e)
{
ManualResetEvent threadStartedSignal = new ManualResetEvent(false);
thread[counter] = new Thread(goThread);
thread[counter].Start(threadStartedSignal);
// wait for the thread to create a local reference.
threadStartedSignal.WaitOne();
counter++;
}
private void goThread(object state)
{
kolejka[counter] = new PictureBox();
var myPictureBox = kolejka[counter];
// signal the other thread, that the counter may be changed.
((ManualResetEvent)state).Set();
myPictureBox .Location = new Point(325, n - 150);
myPictureBox .Image = threading.Properties.Resources.car;
myPictureBox .Size = new Size(20, 37);
this.Invoke((MethodInvoker)delegate
{
this.Controls.Add(myPictureBox );
});
for (int i = 0; i < 500; i++)
{
this.Invoke((MethodInvoker)delegate
{
myPictureBox.Location = new Point(myPictureBox.Location.X, myPictureBox.Location.Y - 3);
this.Refresh();
});
Thread.Sleep(50);
}
}

WPF use a timer to repeat an action

so I am new to WPF and am just trying to make a simple little program. When you hit a start button it will continuosly print fake code until you hit a stop button. I have tried to make it repeat until the stop button is hit 10 different ways but none of them are working. The TextBlock element will update once (or never) and then the whole program becomes unusable and the loading cursor comes up. I would guess that instead of going through a cycle, and then updating the TextBlocks, it is doing everything in the background and not updating visually.
public partial class MainWindow : Window
{
System.Windows.Threading.DispatcherTimer dispatcherTimer = new System.Windows.Threading.DispatcherTimer();
Random r1 = new Random();
bool stop = false;
int numUse
public MainWindow()
{
InitializeComponent();
dispatcherTimer.Interval = new TimeSpan(0, 0, 1);
dispatcherTimer.Start();
}
//Executes when the start button is hit, begins timer
private void Button_Click(object sender, RoutedEventArgs e)
{
do
{
dispatcherTimer.Tick += dispatcherTimer_Tick;
} while (stop == false);
}
//Executes when the stop button is hit, ends timers do while loop
private void Button_Click_1(object sender, RoutedEventArgs e)
{
stop = true;
}
private void dispatcherTimer_Tick(object sender, EventArgs e)
{
numUse = r1.Next(1, 2);
if (numUse == 1)
{
CodeBlock1.Text = "struct group_info init_groups = { .usage = ATOMIC_INIT(2) }; ";
CodeBlock2.Text = "";
CodeBlock3.Text = "struct group_info *groups_alloc(int gidsetsize){ ";
CodeBlock4.Text = "struct group_info *group_info; ";
CodeBlock5.Text = "int nblocks; ";
CodeBlock6.Text = "int i; ";
CodeBlock7.Text = "";
CodeBlock8.Text = "initialize stream";
}
else if (numUse == 2)
{
CodeBlock1.Text = "if (gidsetsize <= NGROUPS_SMALL) ";
CodeBlock2.Text = "group_info->blocks[0] = group_info->small_block; ";
CodeBlock3.Text = " else { ";
CodeBlock4.Text = " for (i = 0; i < nblocks; i++) { ";
CodeBlock5.Text = "b = (void *)__get_free_page(GFP_USER); ";
CodeBlock6.Text = " goto out_undo_partial_alloc; ";
CodeBlock7.Text = "} ";
CodeBlock8.Text = "";
} else
{
}
}
}
}
I have tried for loops, do while, using different methods in different orders. I understand that I likely messed up while going those routes so any method is ok for my purposes. Obviously I am using a Timer in this case.
It is not necessary to repeatedly call dispatcherTimer.Tick += dispatcherTimer_Tick in the while loop of Button_Click. I suspect that while this loop is running, nothing else on the message pump will run, including ticks from the DispatcherTimer.
You could probably do away with stop and merely act on the DispatcherTimer directly by calling Stop() from anywhere in the code.
Perhaps this instead:
public MainWindow()
{
InitializeComponent();
dispatcherTimer.Interval = new TimeSpan(0, 0, 1);
dispatcherTimer.Tick += dispatcherTimer_Tick; // set it up here
}
//Executes when the start button is hit, begins timer
private void Button_Click(object sender, RoutedEventArgs e)
{
dispatcherTimer.Start(); // start timer
}
//Executes when the stop button is hit, ends timers do while loop
private void Button_Click_1(object sender, RoutedEventArgs e)
{
dispatcherTimer.Stop(); // stop timer
}

Stopwatch changing button text in c#

Basically, I've got multiple button in my Form, and I want for it show a Stopwatch in the button.Text when the button is pressed. (Button is modified to be a toggle button.) and to stop and reset the timmer when the button is toggled off. Simple enough it seemed but because I have multiple buttons that could be pressed in any order, and I don't know anything about threading, this seems to be much more difficult that I presumed.
My origional intent was to have a function that constantly runs every second and interates a interager only if the button is pressed using this code:
public void Jogger()//purpose is to step up time[0] every second only when a button is on.
{
while (true)
{
for (int i = 0; i < 16; i++)
{
if (btnstat[i])
time[i]++;
}
Thread.Sleep(1000);
}
}
Problem is, I don't know threading so when I call the function, its stuck doing this and only this.
Either way, once this is called, all i do us call my update function that updates all the buttons including the button.Text which displays the time[0]; (array built around buttons)
Is their a better way of doing this that doesn't cause so much CPU use and/or simply works?
Thanks for all the help!
-John Ivey
Assuming you using checkbox with property Button = Appearence, in event handler for CheckedChanged:
private void CheckBoxCheckedChanged(object sender, EventArgs e)
{
CheckBox checkBox = (CheckBox) sender;
if (checkBox.Checked)
{
Timer timer = new Timer {Interval = 1000};
timer.Tick += Jogger;
timer.Start();
timer.Tag = new CheckboxCounter {CheckBox = checkBox, Time = 0};
checkBox.Tag = timer;
}
else
{
Timer timer = checkBox.Tag as Timer;
if (timer != null)
{
timer.Tag = null;
timer.Stop();
timer.Dispose();
checkBox.Tag = null;
}
}
}
Change your Jogger function:
private void Jogger(object a_sender, EventArgs a_eventArgs)
{
Timer timer = (Timer) a_sender;
CheckboxCounter data = (CheckboxCounter)timer.Tag;
data.Time++;
data.CheckBox.Text = data.Time.ToString();
}
You also need some simple class to store checkbox and current time:
class CheckboxCounter
{
public CheckBox CheckBox;
public int Time;
}
Then you can add any number of checkboxes and just set event CheckedChanged to CheckBoxCheckedChanged.
Try this out. After re-building or running, you should have the new "ButtonTimer" at the top of your ToolBox. Drop a couple on your Form, run it, and see what happens when you click them. Right click them to "Reset" them:
public class ButtonTimer : CheckBox
{
private System.Windows.Forms.Timer Tmr = new System.Windows.Forms.Timer();
private System.Diagnostics.Stopwatch SW = new System.Diagnostics.Stopwatch();
public ButtonTimer()
{
this.Tmr.Interval = 500;
this.Tmr.Tick += new EventHandler(tmr_Tick);
this.Appearance = System.Windows.Forms.Appearance.Button;
this.CheckedChanged += new EventHandler(ButtonTimer_CheckedChanged);
ContextMenuStrip cms = new ContextMenuStrip();
ToolStripItem tsi = cms.Items.Add("Reset");
tsi.Click += new EventHandler(tsi_Click);
this.ContextMenuStrip = cms;
}
protected override void OnLayout(LayoutEventArgs levent)
{
base.OnLayout(levent);
this.Text = TimeSpan.Zero.ToString(#"hh\:mm\:ss");
}
private void ButtonTimer_CheckedChanged(object sender, EventArgs e)
{
if (this.Checked)
{
this.SW.Start();
this.Tmr.Start();
}
else
{
this.SW.Stop();
this.Tmr.Stop();
}
}
private void tmr_Tick(object sender, EventArgs e)
{
this.UpdateTime();
}
private void UpdateTime()
{
this.Text = this.SW.Elapsed.ToString(#"hh\:mm\:ss");
}
private void tsi_Click(object sender, EventArgs e)
{
if (this.SW.IsRunning)
{
SW.Restart();
}
else
{
SW.Reset();
}
this.UpdateTime();
}
}
Application.DoEvents() for simplicity put inside loop . . but it is advisable to start to lean threading . you will just learn how to start thread and how make cross thread safe call
Next simple will be to use backgroundworker . look this http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx
ok here is thread solution also as you wanted . Tested too . as a stop variable i used Tag. But u can inherit button to make state button.it be more clear way . And below code will use one thread per button . So u should make it in one thread to make it better solution . You can modify this code to do all checkings inside one thread . For this you start thread once can make delegate for attaching dinamically count function for each button or you can pass buttons before . With one word there are more than one way to do it. Good luck
this.button1.Click += new System.EventHandler(this.button_Click);
this.button2.Click += new System.EventHandler(this.button_Click);
...and so on
private void button_Click(object sender, EventArgs e)
{
Thread x= new Thread(new ParameterizedThreadStart(Jogger2));
x.Start(sender);
}
private void button_Click(object sender, EventArgs e)
{
Button mybtn=sender as Button;
if((string)mybtn.Tag=="start"){
mybtn.Tag ="";
return;
}
mybtn.Tag = "start";
Thread x= new Thread(new ParameterizedThreadStart(Jogger2));
x.Start(sender);
}
private bool setResult(object obj,string text)
{
if (this.textBox1.InvokeRequired)
{
Func<Button,string, bool > d = new Func<Button,string,bool >(setResult);
return (bool)this.Invoke(d,obj,text);
}
else
{
Button btn=obj as Button;
if (btn != null)
{
btn.Text = text;
if ((string)btn.Tag !="start") return false;
}
return true;
}
}
private void Jogger2(object mybtn)
{
int ii = 0;
while (true)
{
Thread.Sleep(1000);
//replace with your code
ii += 1;
if (!setResult(mybtn, ii.ToString())) break;
}
}

BackGround Thread with timer for application level-WPF Application

I have a wpf application(No MVVM), this application requires several background thread(Runs with specific time interval).
These thread should be on Application Level i.e. if user is on any WPF Window, these threads should be active.
Basically these thread will are using external resources so locking is also required.
Kindly tell me the best way to do this.
If you want to execute an action periodically in a WPF application you can use the DispatcherTimer class.
Put your code as the handler of the Tick event and set the Interval property to whatever you need. Something like:
DispatcherTimer dt = new DispatcherTimer();
dt.Tick += new EventHandler(timer_Tick);
dt.Interval = new TimeSpan(1, 0, 0); // execute every hour
dt.Start();
// Tick handler
private void timer_Tick(object sender, EventArgs e)
{
// code to execute periodically
}
private void InitializeDatabaseConnectionCheckTimer()
{
DispatcherTimer _timerNet = new DispatcherTimer();
_timerNet.Tick += new EventHandler(DatabaseConectionCheckTimer_Tick);
_timerNet.Interval = new TimeSpan(_batchScheduleInterval);
_timerNet.Start();
}
private void InitializeApplicationSyncTimer()
{
DispatcherTimer _timer = new DispatcherTimer();
_timer.Tick += new EventHandler(AppSyncTimer_Tick);
_timer.Interval = new TimeSpan(_batchScheduleInterval);
_timer.Start();
}
private void IntializeImageSyncTimer()
{
DispatcherTimer _imageTimer = new DispatcherTimer();
_imageTimer.Tick += delegate
{
lock (this)
{
ImagesSync.SyncImages();
}
};
_imageTimer.Interval = new TimeSpan(_batchScheduleInterval);
_imageTimer.Start();
}
These three threads a intialized on App_OnStart
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
try
{
_batchScheduleInterval = Convert.ToInt32(ApplicationConfigurationManager.Properties["BatchScheduleInterval"]);
}
catch(InvalidCastException err)
{
TextLogger.Log(err.Message);
}
Helper.SaveKioskApplicationStatusLog(Constant.APP_START);
if (SessionManager.Instance.DriverId == null && _batchScheduleInterval!=0)
{
InitializeApplicationSyncTimer();
InitializeDatabaseConnectionCheckTimer();
IntializeImageSyncTimer();
}
}

Categories