zoukankan      html  css  js  c++  java
  • WPF中定时器与进度条的配合使用(涉及定时器,委托)

    本篇博客涉及定时器,委托中多线程的使用,希望对大家有所帮助~~~

    WPF中定时器使用的注意事项:

       WPF需要使用System.Windows.Threading.DispatcherTimer定时器,而不能使用System.Timers.Timer定时器。因为System.Timers.Timer运行在非UI线程,如果不使用SynchronizingObject属性,则该定时器启动的 子线程与窗体不在一个线程,不能访问WPF窗体中的控件(运行时会报该对象已被其他线程占用的异常),只能通过dialing的方式来访问,而System.Windows.Threading.DispatcherTimer运行在UI线程中,可以访问WPF窗体中的控件。或者,在System.Timers.Timer定时器中使用this.Dispatcher切换到UI线程后使用Invoke或者BeginInvoke方法更新UI画面。

    1.创建System.Timers.Timer定时器并初始化:

    System.Timers.Timer timer; 
    private delegate SetProgress();//声明委托用于更新UI
    public double value = 0; //进度条进度值
    private delegate void AutoMJBuInfoMethod(string model, string pattern, Int32 orgid); //点击按钮使用委托

    public MainWindow() {
    InitializeComponent();
    this.MJpbBar.Maximum = 100;
    this.MJpbBar.Minimum = 0;
       if (timer == null) 
    {
    timer = new System.Timers.Timer();
    timer.Interval = 1000;
    timer.Elapsed += new ElapsedEventHandler(OnTick);;
    }
    }
    private void OnTick(object sender, System.Timers.ElapsedEventArgs e) { timer.AutoReset = false; //是否只触发一次Elapsed法,false(次),true(重复) timer.Enabled = false;//是否引发Elapsed事件 timer.stop(); ProgressBarAction(); //更新进度条方法 timer.AutoReset = true; timer.Enabled= true; timer.Start(); }

    2.定时器执行方法(使用Invoke更新UI画面):

     private bool ProgressBarAction()
    {
     this.Dispatcher.Invoke(DispatcherPriority.Normal, new SetProcess(updateUI));

    MJpbBar.Dispatcher.Invoke(new Action<System.Windows.DependencyProperty, object>(MJpbBar.SetValue),
    System.Windows.Threading.DispatcherPriority.Background, ProgressBar.ValueProperty, value);
    }

    3.更新UI方法:

    private void UpdateUI()
    {
     value = (double)AUTOBUMJBusiness.FinishedMJCount * 100 / AUTOBUMJBusiness.TotalMJCount; //TotalMJCount为总计数量,FinishedMJCount为已完成数量
    
     lblMJProcess.Content = "资料总条数:" + AUTOBUMJBusiness.TotalMJCount + ",已生成:" + AUTOBUMJBusiness.FinishedMJCount;

       //执行结束后隐藏进度条
       if (AUTOBUMJBusiness.TotalMJCount == AUTOBUMJBusiness.FinishedMJCount && AUTOBUMJBusiness.TotalMJCount > 0)
       {
          this.lblMJProcess.Visibility = Visibility.Hidden;
          this.MJpbBar.Visibility = Visibility.Hidden;
          this.btnMJ.Visibility = Visibility.Visible;
       }

    }

    4.点击事件(点击按钮后执行另一个方法会堵塞线程,直到另一个线程执行结束,此时页面UI不会更新,所以此处使用委托开启另一条线程来执行这个方法):

    private void btn_click(object sender, RoutedEventArgs e)
    {

       try
    {

           this.lblMJProcess.Visibility = Visibility.Visible;
           this.MJpbBar.Visibility = Visibility.Visible;
           this.btnMJ.Visibility = Visibility.Hidden;

         AUTOBUMJBusiness oAUTOBUMJBusiness = new AUTOBUMJBusiness();
    AutoMJBuInfoMethod oAuotoMJBuInfo = new AutoMJBuInfoMethod(oAUTOBUMJBusiness.DoAction);
    oAuotoMJBuInfo.BeginInvoke(this.txtModel.Text.ToString().ToUpper().Trim(), this.txtPattern.Text.ToString().ToUpper().Trim(), Convert.ToInt32(this.txtOrgid.Text.ToString().Trim()), null, null);

        }
        catch (Exception ex)
        {
           _log.Info("转MainWindow程序出错" + ":" + ex.Message + "." + DateTime.Now);
        }

    }

        在用户点击按钮后,主线程会被堵塞,直到点击事件中的DoAction全部执行完,才会执行下面的程序。因此会引发页面UI无法更新的问题,需要使用BeginInvoke方法来另开一条线程,用来执行DoAction方法,不会影响主线程的工作,从而不影响页面UI更新。

  • 相关阅读:
    各种锁
    几百兆的sql文件无法编辑
    og4j1.x升级log4j2.x及异步日志开启
    TSNE/分析两个数据的分布
    _tkinter.TclError: no display name and no $DISPLAY environment variable
    split分割文件
    ubuntu+jdk
    进程操作
    ImportError: No module named apex
    Ubuntu 16.04.4安装Anaconda
  • 原文地址:https://www.cnblogs.com/qianlang/p/10350906.html
Copyright © 2011-2022 走看看