-3

I have a WinForms app which I'd like to have a clock in the bottom left. So far I managed to display the time when it launched, but I can't make it update itself. I tried to use a BackgroundWorker but since it is on a different thread it errors out so it can't change anything.

I hope there's a somewhat easy fix to my problem

Thanks in advance!

Edit 1 would be adding some of the code

DateTime output;

Random rnd = new Random();

private void GetTime_DoWork(object sender, DoWorkEventArgs e)
{
    GetTime.ReportProgress(rnd.Next(1, 62));
}
private void GetTime_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    output = DateTime.Now;
    TimeLabel.Text = output.Hour + ":" + output.Minute + ":" + output.Second;
    DateLabel.Text = output.ToString("yyyy-MM-dd, dddd");
}

"output" is a DateTime type variable where I'd like to store the values of the current time The random number generator is only used to change the progress TimeLabel only outputs time DateLabel outputs in 2020-01-01 Wednesday format

Edit 2: Using Timer element worked, Thread.Sleep(1000); isn't used since it would halt everything else on the form

Adding new code:

public Form1()
        {
            InitializeComponent();
            TimeUpdate.Start();
        }

//...

private void TimeUpdate_Tick(object sender, EventArgs e)
        {
            output = DateTime.Now;
            TimeLabel.Text = output.ToString("HH:mm:ss");
            DateLabel.Text = output.ToString("yyyy-MM-dd, dddd");
        }
//TimeUpdate is the name of the Timer
theHeXaGoNdev
  • 19
  • 1
  • 1
  • 5
  • 2
    use a `Timer` instead of a background worker. – Daniel A. White Jul 07 '20 at 21:10
  • The standard Timer control can be found in the ToolBox under the "Components" category. Set it's `.Interval` property to 1000 (once per second) and double click it to get the `Tick()` event. Put your code in that event to update the current time. Make sure to turn it on with the Enabled property. – Idle_Mind Jul 07 '20 at 21:30
  • 1
    @Richardissimo Checking `InvokeRequired` isn't required anywhere here. Even if the OP will opt for a BackGroundWorker, `ProgressChanged` is raised in the UI Thread. If a Timer is used, the Tick event is raised in the UI Thread. If a long runnng Task is used (though I don't see why one would choose it for this), the `Progress` delegate is called in the UI Thread, etc. – Jimi Jul 07 '20 at 22:23
  • @Jimi Note that the question was edited half an hour after my comment. Take a look at what it looked like before that edit - there was no code supplied at all, hence why my comment said "without seeing any code". – Richardissimo Jul 07 '20 at 22:29
  • òRichardissimo It doesn't change the core matter. The question is about the BackGroundWorker and it was from the beginning. I saw the edit. `InvokeRequired` (besides being rarely used these days), doesn't find any use anywhere. You, of course, don't `Invoke()` from the `DoWork` event (ever). – Jimi Jul 07 '20 at 22:34
  • If you insist on using `BackgroundWorker`, you can. See first two marked duplicates for how to have the worker report progress to the UI thread, where you can update UI without using `Invoke()`. However, wasting a thread pool thread on an indefinitely-running loop is really poor practice. What you really want is to use a timer object. See other marked duplicates. – Peter Duniho Jul 15 '20 at 16:53

1 Answers1

0

Still think you should use the standard Timer control.

If you want to keep that BackgroundWorker, though, then you need to make it loop forever and pause for one second between updates:

private void Form1_Load(object sender, EventArgs e)
{
    GetTime.RunWorkerAsync();
}

private void GetTime_DoWork(object sender, DoWorkEventArgs e)
{
    while(true)
    {
        GetTime.ReportProgress(rnd.Next(1, 62));
        System.Threading.Thread.Sleep(1000);
    }
}

private void GetTime_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    output = DateTime.Now;
    TimeLabel.Text = output.ToString("h:mm:ss tt");
    DateLabel.Text = output.ToString("yyyy-MM-dd, dddd");
}

Since it is a background thread, it will automatically be killed when the form is closed.

Idle_Mind
  • 38,363
  • 3
  • 29
  • 40