Digital Clock in C # with Threads

1

I have this code in c # that runs a digital clock:

  public partial class Form1 : Form
  {
      Thread hilo;

      public Form1()
      {
           InitializeComponent();
      }

      delegate void TiempoDelegado();

      public void CambiarTiempo()
      {
         if (this.InvokeRequired) 
         {
            TiempoDelegado delegado = new TiempoDelegado(CambiarTiempo);
            this.Invoke(delegado);
         }
         else
         {
            label1.Text = DateTime.Now.Hour.ToString("00") + ":" + DateTime.Now.Minute.ToString("00") + ":" + DateTime.Now.Second.ToString("00");
         }
      }

      private void Tiempo()
      {
          Thread.Sleep(100);
          CambiarTiempo();
          Tiempo();
      }

      private void button1_Click(object sender, EventArgs e)
      {
          hilo = new Thread(Tiempo);
          hilo.Start();
      }
  }

If you run the clock correctly, but when I want to close the application, I get this error:

How can I solve this?

    
asked by 04.07.2018 в 19:52
source

2 answers

0

A very easy way to solve the problem would be to control the exception of ObjectDisposedException in Invoke

The code would look like this:

public partial class Form1 : Form
{
    Thread hilo;

    public Form1()
    {
        InitializeComponent();
    }


    delegate void TiempoDelegado();

    public void CambiarTiempo()
    {
        if (this.InvokeRequired)
        {
            TiempoDelegado delegado = new TiempoDelegado(CambiarTiempo);
            try
            {
                this.Invoke(delegado);
            }
            catch (ObjectDisposedException ex)
            {
                return;
            }
        }
        else
        {
            label1.Text = DateTime.Now.Hour.ToString("00") + ":" + DateTime.Now.Minute.ToString("00") + ":" +
                          DateTime.Now.Second.ToString("00");
        }
    }

    private void Tiempo()
    {
        Thread.Sleep(100);
        if (this.Disposing || this.IsDisposed)
            return;
        CambiarTiempo();
        Tiempo();
    }

    private void button1_Click(object sender, EventArgs e)
    {
        hilo = new Thread(Tiempo);
        hilo.Start();
    }
}

Regards,

    
answered by 05.07.2018 / 09:02
source
0

Try this:

1) You install the Reactive Extensions package in nuget (the latest version 3.x, not the 4)

2) You import the following namespaces:

using System.Theading;
using System.Reactive;
using System.Reactive.Linq;

3) You add a private field like this:

private IDisposable timer;

4) In the form's constructor, after calling the initialization method, you put this:

timer = Observable
    .Timer(TimeSpan.FromSeconds(1)) // crea un timer observable, que está emitiendo eventos cada segundo
    .Select(_ => DateTime.Today.ToShortTimeString()) // obtenemos la hora y la formateamos como texto
    .ObserveOn(SynchronizationContext.Current) // pasamos el evento al hilo principal de la ui
    .Subscribe(dateText => label1.Text = dateText); // el texto con la hora lo asignamos al label

5) And finally, so that the timer is not "active" by making the dispose of the form and you mark error, move the method "Dispose" that is in the code generated by the form designer and put it in your code behind, and modify it like this:

protected override void Dispose(bool disposing)
{
    if (disposing && (components != null))
    {
        components.Dispose();
    }
    if (disposing && timer != null)
    { 
        timer.Dispose();
        timer = null;
    }
    base.Dispose(disposing);
}

With that you avoid delegates and timers and all that, less lines of code, everything is in one place, etc.

    
answered by 05.07.2018 в 05:15