Making a Chronometer c# - winforms

I'm trying to make a chronometer forms application that works both as a stopwatch and a countdown with ticking an option.
Problem is that I can't seem to be able to draw the miliseconds.
Right now, without the miliseconds the Tick method looks like this:
private void timer_Tick(object sender, EventArgs e)
{
if (timespan.TotalSeconds > 0)
{
timespan = timespan.Add(new TimeSpan(0, 0, -1));
updateNumericUpDowns();
}
else
{
timerCountown.Stop();
}
}
The method for updating the UI:
private void updateNumericUpDowns()
{
numericUpDownSeconds.Value = Convert.ToInt32(timespan.Seconds);
numericUpDownMinutes.Value = Convert.ToInt32(timespan.Minutes);
numericUpDownHours.Value = Convert.ToInt32(timespan.Hours);
}
Help is appreciated, tnx everyone!

Not sure I'm following. Why not just use timespan.Milliseconds?
As it is, you're using hours, minutes, and seconds. If you want to show the milliseconds, then add that.

I don't think I would trust "timer_Tick" for the millisecond resolution: If the system is under heavy load, will a tick be slower or faster than 1 second? (Will that affect the number of elapsed millis?) Try comparing the current time to a known starting time.
private DateTime startTime;
void StartTimer() {
startTime = DateTime.Now;
//start timer
}
private void timer_Tick(object sender, EventArgs e)
{
var currentTime = DateTime.Now;
timespan = currentTime - startTime; //positive
bool hasCountdownTerminated = ... //maybe something like timespan < duration + timerResolution
if (hasCountdownTerminated)
{
timerCountown.Stop();
}
else
{
updateNumericUpDowns();
}
}
void updateNumericUpDowns() {
//use timespan.Milliseconds;
}

Related

OnAfterRender or OnInitializedAsync function to refresh data?

I'd like to refresh my data each minute. for this, I use a timer.
`
protected override async Task OnInitializedAsync()
{
await base.OnInitializedAsync();
//Configuration des graphiques
Alert.Info("OnInitializedAsync");
timer = new System.Threading.Timer(async (object? stateInfo) =>
{
loading = true;
GetDataAPI();
}, new System.Threading.AutoResetEvent(false), 2000, 2000);
}
`
this work fine, but when I load the page for the fisrt time, It spend a long time before to load data. when I delete the Time it's very faster.
so my question, is it in the OnInitializedAsync that I use the timer ? I've read a lot of documention on the cycle but don't really see the difference between OnAfterRender or OnInitializedAsync.
should I load data the first time in OnAfterRender with FirstRender ? and then the timer in OnInitializedAsync ?
thanks for your help.
You can break out the timer into a separate class with an event to drive updates:
public class MyTimer
{
private System.Timers.Timer _timer = new System.Timers.Timer();
public event EventHandler<ElapsedEventArgs>? TimerElapsed;
public MyTimer(double period)
=> SetTimer(period);
private void SetTimer(double period)
{
_timer = new System.Timers.Timer(period);
_timer.Elapsed += OnTimedEvent;
_timer.AutoReset = true;
_timer.Enabled = true;
}
private void OnTimedEvent(object? source, ElapsedEventArgs e)
=> this.TimerElapsed?.Invoke(this, e);
}
And then you can use it like this. I've added a simple message that is updated every 5 seconds to demo getting new data. Note there's no delay on the initial load.
#page "/"
#implements IDisposable
<PageTitle>Index</PageTitle>
<h1>Hello, world!</h1>
Welcome to your new app.
<div class="alert alert-info">
#message
</div>
#code {
private MyTimer? timer;
private string message = DateTime.Now.ToLongTimeString();
private bool isGettingData;
protected async override Task OnInitializedAsync()
{
await this.GetDataAsync();
// Set for every 5 seconds
timer = new(5000);
timer.TimerElapsed += this.OnTimeElapsed;
}
private async void OnTimeElapsed(object? sender, EventArgs e)
{
await this.GetDataAsync();
// Update the UI
await this.InvokeAsync(StateHasChanged);
}
private async ValueTask GetDataAsync()
{
// Only get the data again if we finished the last get
if (isGettingData)
return;
isGettingData = true;
// emulate async fetching data
await Task.Delay(100);
message = DateTime.Now.ToLongTimeString();
isGettingData = false;
}
public void Dispose()
{
if (timer is not null)
timer.TimerElapsed -= this.OnTimeElapsed;
timer = null;
}
}

Can anyone tell me how to restart dispatcher timer in c# wpf app?

I am write Auction app in WPF and I don't know how to restart my DispatcherTimer,
This is code for Timer.
Timer = new DispatcherTimer();
Timer.Interval = new TimeSpan(0,0,1);
Timer.Tick += Timer_Tick;
void Timer_Tick(object sender, object e)
{
if (time > 1)
{
time--;
timertxt.Text = string.Format("00:0{0}:{1}", time / 60, time % 60);
}
else
{
Timer.Stop();
MessageBox.Show("Auction is off !","Error !",MessageBoxButton.OK,MessageBoxImage.Error);
AuctionIDtxt.Clear();
Productnametxt.Clear();
pricetxt.Clear();
descriptiontxtblock.Clear();
winnerislbl.IsVisible.Equals(true);
winnerislbl.Content = "winner is:" ;
winuserlbl.Content = UserLbl;
}
}
Just call Timer.Start().
Start resets the timer Interval.
From the documentation

how to start progress-bar after sometime of interval

I have wpf application with progressbar. I want to start it after 1 minute. my progress bar working properly just want to start after specific time period.
code for progressbar
public login()
{
InitilizeComponent()
DispatcherTimer timer= new Timer(1000);
timer.Elapsed+= timer_Elapsed;
timer.start();
}
void timer_Elapsed(object sender, ElapsedEventArgs e)
{
thsi.Dispatcher.Invoke(DispatcherProperty.Normal,(Action)() =>
{
if (progressBar<20)
{
progressBar.value+=1;
}
else
{
timer.stop();
}
}
)
}
You could use a combination of async/await methods and a timer to achieve this:
DispatcherTimer timerProgressBar;
public login()
{
InitializeComponent();
//Create the timer
timerProgressBar = new DispatcherTimer();
timerProgressBar.Interval = new TimeSpan(0,0,1);
timerProgressBar.Tick += timerProgressBar_Tick;
//Start waiting
WaitForProgressBar();
}
void timerProgressBar_Tick(object sender, EventArgs e)
{
this.Dispatcher.Invoke(() =>
{
if (progressBar.Value < 20)
progressBar.Value++;
else
timerProgressBar.Stop();
});
}
/// <summary>
/// Begins waiting for 1 minute before starting the timer.
/// </summary>
public async void WaitForProgressBar()
{
await Task.Run(() => System.Threading.Thread.Sleep(new TimeSpan(0, 1, 0)));
timerProgressBar.Start();
}
Using the async method, this will keep your UI responsive during the wait period. If this isn't what was intended then simply change the async methods to synchronous.

Update Current time in every two minutes in Silverlight

I have silverlight application which is having Current time and date , ia m getting this from WCF Service now i want to update Current Date and time in every minute.
How to achieve that ?
My service code is :
[OperationContract]
public DateTime GetDateTime()
{
return DateTime.Now ;
}
My xaml.cs is :
void Welcome_Loaded(object sender, RoutedEventArgs e)
{
SessionService.SLWebServiceClient client = new SessionService.SLWebServiceClient();
client.GetDateTimeCompleted += new EventHandler<SessionService.GetDateTimeCompletedEventArgs>(client_GetDateTimeCompleted);
client.GetDateTimeAsync();
}
void client_GetDateTimeCompleted(object sender, SessionService.GetDateTimeCompletedEventArgs e)
{
lblDateTime.Text = e.Result.ToString();
}
Thanks.
You may use a DispatcherTimer to call the WCF service every two minutes. Here's how:
// Every 2 minutes calls the timer_Tick handler
DispatcherTimer timer = new DispatcherTimer() { Interval = new TimeSpan(0, 2, 0) };
timer.Tick += new EventHandler(timer_Tick);
timer.Start();
private void timer_Tick(object sender, EventArgs e)
{
SessionService.SLWebServiceClient client = new SessionService.SLWebServiceClient();
client.GetDateTimeCompleted += new EventHandler<SessionService.GetDateTimeCompletedEventArgs>(client_GetDateTimeCompleted);
client.GetDateTimeAsync();
}
Hope it helps!
Bruno

WPF & Multi-threading questions

I'm working on building a multi-threaded UI. I would like long processes to be handled by the BackgroundWorker class, and have a small timer on the UI to keep track of how long the process is taking. It's my first time building such a UI, so I'm reading up on related resources on the web. My test code is thus:
private BackgroundWorker worker;
private Stopwatch swatch = new Stopwatch();
private delegate void simpleDelegate();
System.Timers.Timer timer = new System.Timers.Timer(1000);
string lblHelpPrevText = "";
private void btnStart_Click(object sender, RoutedEventArgs e)
{
try
{
worker = new BackgroundWorker(); //Create new background worker thread
worker.DoWork += new DoWorkEventHandler(BG_test1);
worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(BG_test1end);
worker.RunWorkerAsync();
simpleDelegate del = new simpleDelegate(clockTicker);
AsyncCallback callBack = new AsyncCallback(clockEnd);
IAsyncResult ar = del.BeginInvoke(callBack, null);
lblHelpText.Text = "Processing...";
}
finally
{
worker.Dispose(); //clear resources
}
}
private void clockTicker()
{
//Grab Text
simpleDelegate delLblHelpText = delegate()
{ lblHelpPrevText = this.lblHelpText.Text; };
this.Dispatcher.BeginInvoke(DispatcherPriority.Send, delLblHelpText);
//Start clock
timer.Elapsed += new ElapsedEventHandler(clockTick);
timer.Enabled = true;
swatch.Start();
}
private void clockTick(object sender, ElapsedEventArgs e)
{
simpleDelegate delUpdateHelpTxt = delegate()
{ this.lblHelpText.Text = String.Format("({0:00}:{1:00}) {2}", swatch.Elapsed.Minutes, swatch.Elapsed.Seconds, lblHelpPrevText); };
this.Dispatcher.BeginInvoke(DispatcherPriority.Send, delUpdateHelpTxt);
}
private void BG_test1(object sender, DoWorkEventArgs e)
{
//this.lblHelpText.Text = "Processing for 10 seconds...";
Thread.Sleep(15000);
}
private void BG_test1end(object sender, RunWorkerCompletedEventArgs e)
{
this.lblHelpText.Text = "Process done.";
this.timer.Enabled = false;
this.swatch.Stop();
this.swatch.Reset();
}
static void clockEnd(IAsyncResult ar)
{
simpleDelegate X = (simpleDelegate)((AsyncResult)ar).AsyncDelegate;
X.EndInvoke(ar);
}
The idea is when the button is clicked, we take the status text from a Label (e.g. "Processing...") then append the time onto it every second. I could not access the UI elements from the Timer class as it's on a different thread, so I had to use delegates to get and set the text.
It works, but is there a better way to handle this? The code seems much for such a basic operation. I'm also not fully understanding the EndInvoke bit at the bottom. I obtained the snippet of code from this thread Should One Always Call EndInvoke a Delegate inside AsyncCallback?
I understand the idea of EndInvoke is to receive the result of BeginInvoke. But is this the correct way to use it in this situation? I'm simply worried about any resource leaks but when debugging the callback appears to execute before my timer starts working.
Don't use a separate timer to read the progress of your BackgroundWorker and update the UI. Instead, make the BackgroundWorker itself "publish" its progress to the UI directly or indirectly.
This can be done pretty much anyway you want to, but there's a built-in provision exactly for this case: the BackgroundWorker.ProgressChanged event.
private void BG_test1(object sender, DoWorkEventArgs e)
{
for(var i = 0; i < 15; ++i) {
Thread.Sleep(1000);
// you will need to get a ref to `worker`
// simplest would be to make it a field in your class
worker.ReportProgress(100 / 15 * (i + 1));
}
}
This way you can simply attach your own handler to ProgressChanged and update the UI using BeginInvoke from there. The timer and everything related to it can (and should) go.
You can use timer to update UI. It is normal practice. Just instead of System.Timer.Timer I suggest use System.Windows.Threading.DispatcherTimer. The DispatcherTimer runs on the same thread as the Dispatcher. Also, instead of BackgroundWorker you can use ThreadPool.
Here is my sample:
object syncObj = new object();
Stopwatch swatch = new Stopwatch();
DispatcherTimer updateTimer; // Assume timer was initialized in constructor.
void btnStart_Click(object sender, RoutedEventArgs e) {
lock (syncObj) {
ThreadPool.QueueUserWorkItem(MyAsyncRoutine);
swatch.Start();
updateTimer.Start();
}
}
void updateTimer_Tick(object sender, EventArgs e) {
// We can access UI elements from this place.
lblHelpText.Text = String.Format("({0:00}:{1:00}) Processing...", swatch.Elapsed.Minutes, swatch.Elapsed.Seconds);
}
void MyAsyncRoutine(object state) {
Thread.Sleep(5000);
lock (syncObj)
Dispatcher.Invoke(new Action(() => {
swatch.Stop();
updateTimer.Stop();
lblHelpText.Text = "Process done.";
}), null);
}
private void button1_Click(object sender, EventArgs e)
{
string strFullFilePath = #"D:\Print.pdf";
ProcessStartInfo ps = new ProcessStartInfo();
ps.UseShellExecute = true;
ps.Verb = "print";
ps.CreateNoWindow = true;
ps.WindowStyle = ProcessWindowStyle.Hidden;
ps.FileName = strFullFilePath;
Process.Start(ps);
Process proc = Process.Start(ps);
KillthisProcess("AcroRd32");
}
public void KillthisProcess(string name)
{
foreach (Process prntProcess in Process.GetProcesses())
{
if (prntProcess.ProcessName.StartsWith(name))
{
prntProcess.WaitForExit(10000);
prntProcess.Kill();
}
}
}

Resources