es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Cronómetro de Multihilo en WinForms

Quiero ejecutar un temporizador cada 10 milisegundos y actualizar la cadena de etiqueta de la interfaz de usuario. He creado la Clase TimerController, donde puedo configurar las propiedades de System.Threading.Timer.

 class TimerControl
{
    private Timer _timer;

    public DateTime StartTime { get; private set; }
    public TimeSpan CurrentElapsedTime { get; private set; }
    public TimeSpan TotalElapsedTime { get; private set; }
    public event EventHandler Tick;
    public bool IsTimerRunning { get; private set; }
    public string CurrentElapsedTimeString { get; private set; } = "";
    public TimerCallback TimerAction { get; private set; }
    public object TimerParametr { get; private set; }
    public int DueTime { get; private set; }
    public int Period { get; private set; }

    public TimerControl(TimerCallback timerAction, object state, int dueTime, int period)
    {
        StartTime = DateTime.Now;
        CurrentElapsedTime = TimeSpan.Zero;
        TotalElapsedTime = TimeSpan.Zero;
        TimerAction = timerAction;
        TimerParametr = state;
        DueTime = dueTime;
        Period = period;

    }

    public void StartTimer()
    {
        StartTime = DateTime.Now;
        TotalElapsedTime = CurrentElapsedTime;
        IsTimerRunning = true;
        if (_timer == null)
            _timer = new Timer(TimerAction, TimerParametr, DueTime, Period);
        else
            _timer.Change(DueTime, Period);
    }
    public void StopTimer()
    {
        _timer.Change(0, -1);
    }
}

Creo el objeto TimerControl en MainForm.cs y necesito crear una función que sea activada por el temporizador. Esta función debe actualizar la etiqueta de tiempo de la interfaz de usuario. Pero en esta función no tengo acceso a la interfaz de usuario. ¿Cómo lo arreglo?

TimerControl timerControl = new TimerControl(StopWatchTimer,null, 0, 10); 

    public MainForm()
    {
        InitializeComponent();
    }

    private void btn_timerStart_Click(object sender, EventArgs e)
    {
        if(btn_timerStart.Text == "Start")
        {
            timerControl.StartTimer();
            btn_timerStart.Text = "Stop";
        }
        else
        {
            timerControl.StopTimer();
            btn_timerStart.Text = "Start";
        }
    }
    // Función de temporizador de devolución de llamada
    private static void StopWatchTimer(object label)
    {
        // labelTime =       // labelTime no existe en el contexto actual
    }
}

}

Tags:  , , , ,

Answer

  1. Avatar for davy.ai

    Para solucionar este problema, puede pasar la etiqueta como parámetro al método StopWatchTimer al crear el objeto TimerControl. Luego, puede convertir el parámetro al tipo de etiqueta y actualizar su propiedad de texto desde dentro de la función de devolución de llamada del temporizador.

    Aquí hay un fragmento de código actualizado:

    TimerControl timerControl = new TimerControl(StopWatchTimer, labelTime, 0, 10);
    
    public MainForm()
    {
        InitializeComponent();
    }
    
    private void btn_timerStart_Click(object sender, EventArgs e)
    {
        if(btn_timerStart.Text == "Iniciar")
        {
            timerControl.StartTimer();
            btn_timerStart.Text = "Detener";
        }
        else
        {
            timerControl.StopTimer();
            btn_timerStart.Text = "Iniciar";
        }
    }
    
    // Función de devolución de llamada del temporizador
    private static void StopWatchTimer(object label)
    {
        if(label is Label timeLabel)
        {
             timeLabel.Invoke((MethodInvoker)delegate 
             {
                 timeLabel.Text = DateTime.Now.ToString("HH:mm:ss:fff");
             });
        }
    }
    

    En el código anterior, convierto el parámetro de etiqueta a un tipo Label utilizando una declaración if, y luego uso el método Invoke para actualizar de manera segura la propiedad de texto de la etiqueta desde dentro de la función de devolución de llamada del temporizador.

    Tenga en cuenta que el objeto labelTime en la clase MainForm debe declararse como una variable pública para que esto funcione. Además, el texto de su etiqueta puede actualizarse con el tiempo usando el método DateTime.Now.ToString.

Comments are closed.