【问题标题】:MultiThread stopWatch timer in WinFormsWinForms 中的多线程秒表计时器
【发布时间】:2022-01-06 03:33:15
【问题描述】:

我想每 10 毫秒运行一次计时器并更新 GUI 标签字符串。我已经创建了 TimerController 类,是否可以设置 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);
    }

我在 MainForm.cs 中创建了 TimerControl 对象,我需要创建函数,该函数将由计时器触发。此功能应更新 GUI 时间标签。但在这个功能中,我无法访问 GUI。如何解决?

TimerControl timerControl = new TimerControl(StopWatchTimer,null, 0, 10); 
    
    public MainForm()
    {
        InitializeComponent();
    }

    

    private void btn_timerStart_Click(object sender, EventArgs e)
    {
        if(btn_timerStart.Text == "Старт")
        {
            timerControl.StartTimer();
            btn_timerStart.Text = "Стоп";
        }
        else
        {
            timerControl.StopTimer();
            btn_timerStart.Text = "Старт";
            
            
        }
    }
    // Callback timer funnction
    private static void StopWatchTimer(object label)
    {
       
        //labelTime =       // labelTime doesnt exist in current context
    }
}

}

【问题讨论】:

  • 你没有访问权限,因为你写了一个静态方法:private static void StopWatchTimer,他们不能访问实例变量。你为什么把它变成静态的?删除它,您应该可以访问。但当心!由于您没有使用 WinForms.Timer 类,因此您的回调操作将在不同的线程上执行,如果您尝试在其中修改 GUI 元素,您将收到异常
  • 为什么不用内置的System.Windows.Forms.Timer组件?
  • I want to run timer every 10 miliseconds 无论如何,更新 GUI 时使用的时间太短了。

标签: c# multithreading winforms user-interface timer


【解决方案1】:

我就是这样做的,一切正常。

public partial class MainForm : Form
{

    TimerControl timerControl;
    public MainForm()
    {
        InitializeComponent();
        timerControl = new TimerControl(StopWatchTimer, l_timer, 0, 10);
    }

    private void btn_timerStart_Click(object sender, EventArgs e)
    {
        if(btn_timerStart.Text == "Старт")
        {
            timerControl.StartTimer();
            btn_timerStart.Text = "Стоп";
        }
        else
        {
            timerControl.StopTimer();
            btn_timerStart.Text = "Старт";
            
            
        }
    }

    private  void StopWatchTimer(object label)
    {
        Label timeLabel = (Label)label;
        TimeSpan elapsed = DateTime.Now - timerControl.StartTime;
        this.Invoke(new MethodInvoker(delegate ()
        {
            timeLabel.Text = elapsed.ToString(@"ss\.ff");
        }));
    }
}

enter image description here

【讨论】:

  • 您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center
  • 你应该看看微软的反应式框架。然后你可以这样做:var startTime = DateTime.Now; Observable.Interval(TimeSpan.FromMilliseconds(10.0)).Select(x => (DateTime.Now - startTime).ToString(@"ss\.ff")).ObserveOn(l_timer).Subscribe(x => timeLabel.Text);
猜你喜欢
  • 2010-10-11
  • 1970-01-01
  • 1970-01-01
  • 2012-03-02
  • 2014-09-03
  • 2015-06-12
  • 2015-10-20
  • 2012-03-10
  • 1970-01-01
相关资源
最近更新 更多