wpf计时器应用程序的多个调度计时器:同时运行多个计时器

时间:2017-02-28 06:06:18

标签: c# wpf dispatchertimer

读取多个stackoverflow,代码项目解决方案,无法集成到我的问题中。

在一个窗口中加载的usercontrol中有一个datagrid。 DataGrid中的每个DataRow代表一个计时器设置。

像:

timer name  : Test 1 , Timer : 1h 3m
timer name  : Test 2 , Timer : 2h 2m
timer name  : Test 3 , Timer : 3h 1m

选择一行,单击按钮Start,启动该行的计时器。并且通过调度程序tick事件,它会更新我已经完成的网格。现在我必须启动另一个(或两个或......)计时器,它将同时执行相同的操作。我坚持这个。让我分享一下我的尝试!

mainwindow.xaml.cs中的

btnStartClickEvent

if (btnStart.Content.ToString() == "Start")
        {
            if (_AUC == ActiveUserControl.Grid)
            {
                runningRow = (TaskGridData)_TG.dgEmployee.SelectedItem;
                if (runningRow != null)
                {
                    currentlyRunningID.Add(runningRow.ID);
                    btnStart.Content = "Stop";
                    //worker.RunWorkerAsync(runningRow);
                    StartTimer(runningRow);
                }
            }
        }
        else if (btnStart.Content.ToString() == "Stop")
        {
            btnStart.Content = "Start";
            StopTimer();

        }
 private DateTime TimerStart { get; set; }
    private void StartTimer(TaskGridData tgd)
    {
        dispatcherTimer = new DispatcherTimer();

        dispatcherTimer.Interval = new TimeSpan(0, 0, 0, 1, 0);
        dispatcherTimer.Tick += new EventHandler(dispatcherTimer_Tick);
        TimerStart = DateTime.Now;
        dispatcherTimer.Start();
        //worker.RunWorkerAsync();

        //string etime = DateTime.Now.Second.ToString();
    }

    private void StopTimer()
    {
        dispatcherTimer.Stop();
    }
private void dispatcherTimer_Tick(object sender, EventArgs e)
    {
        var currentValue = DateTime.Now - TimerStart;
        runningRow.Duration = DurationValueToString(currentValue);
        temp = (List<TaskGridData>)_TG.dgEmployee.ItemsSource;
        foreach (TaskGridData item in temp)
        {
            if (item.ID == runningRow.ID)
            {
                item.Duration = DurationValueToString(DurationStringToVlaue(item.Duration) - DurationStringToVlaue(runningRow.Duration));
                break;
            }
        }
        //_TG.dgEmployee.ItemsSource = null;
        //_TG.dgEmployee.ItemsSource = temp;
        Thread NewThreadforStartProcessAfterTraining = new Thread(() => UpdateGrid());
        NewThreadforStartProcessAfterTraining.IsBackground = true;
        NewThreadforStartProcessAfterTraining.SetApartmentState(ApartmentState.STA);
        NewThreadforStartProcessAfterTraining.Start();

    }
    private void UpdateGrid()
    {
        this.Dispatcher.Invoke(DispatcherPriority.Normal, new Action(() =>
        {
            _TG.dgEmployee.ItemsSource = null;
            _TG.dgEmployee.ItemsSource = temp;
        }));

    }

我知道此代码适用于单个计时器。如果我单击第二行并尝试启动计时器,则在tick事件中出现错误,running row被发现为null。

我想知道如何保留此代码并使其适用于多个计时器。可能是多线程的。这样做的指南将非常有用。

1 个答案:

答案 0 :(得分:0)

    Thread NewThreadforStartProcessAfterTraining = new Thread(() => UpdateGrid());
    NewThreadforStartProcessAfterTraining.IsBackground = true;
    NewThreadforStartProcessAfterTraining.SetApartmentState(ApartmentState.STA);
    NewThreadforStartProcessAfterTraining.Start();

在此上下文中,启动新STA线程的所有上述部分都是不必要的,因为您无法以这种方式更新可视树。 您可以在我以前的一个答案中找到使用STA线程的正确示例:https://stackoverflow.com/a/42473167/6996876

尝试理解WPF中线程亲和性的概念。

您只需要一个UpdateGrid(),您必须将UI工作委派给调度员。

此外,已在此处解释将参数传递给Tick事件:https://stackoverflow.com/a/16380663/6996876 在您的情况下,您可能希望更改当前唯一runningRow,以便将其传递给事件。