多线程更新UI的常用方法

开发Winform或者WPF相关GUI程序中,遇到执行耗时程序片段,并且需要在ui界面上实时展示状态信息的问题时,为了防止界面出现假死状态,会用到多线程技术,异步跨线程访问ui界面元素;下面总结下Winform和WPF中常用的几种异步跨线程访问ui界面的技术。

Winform中常用技术

1、采用BackgroundWorker控件

public partial class Form1 : Form
    {
        private BackgroundWorker worker;
        public Form1()
        {
            InitializeComponent();
            worker = new BackgroundWorker();
            worker.WorkerReportsProgress = true;// To report progress from the background worker we need to set this property
            worker.DoWork += worker_DoWork;// This event will be raised on the worker thread when the worker starts
            worker.ProgressChanged += worker_ProgressChanged;// This event will be raised when we call ReportProgress
        }

        private void worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            progressBar1.Value = e.ProgressPercentage;
            lblPercent.Text = string.Format("{0}%", e.ProgressPercentage);
            if (e.ProgressPercentage == 100)
            {
                MessageBox.Show("数据处理完毕!");
            }
        }

        private void worker_DoWork(object sender, DoWorkEventArgs e)
        {
            for (int i = 1; i <= 100; i++)
            {
                // Report progress to ‘UI‘ thread
                worker.ReportProgress(i);
                Thread.Sleep(100);
            }
        }

        private void btnCompute_Click(object sender, EventArgs e)
        {
            //Start the background worker
            worker.RunWorkerAsync();
        }
    }

2、采用Timer控件

public partial class Form1 : Form
    {
        private Timer timer;
        private int current;
        public Form1()
        {
            InitializeComponent();
            timer = new Timer();
            timer.Interval = 500;
            timer.Tick += timer_Tick;
        }

        private void timer_Tick(object sender, EventArgs e)
        {
            progressBar1.Value = current;
            lblPercent.Text = string.Format("{0}%", current);
            if (current == 100)
            {
                timer.Stop();
                MessageBox.Show("数据处理完毕!");
            }
        }

        private void btnCompute_Click(object sender, EventArgs e)
        {
            Thread thread = new Thread(new ThreadStart(doWork));
            thread.Start();
            timer.Start();
        }

        private void doWork()
        {
            for (int i = 1; i <= 100; i++)
            {
                current = i;
                Thread.Sleep(100);
            }
        }
    }

3、采用委托的方式

public partial class Form1 : Form
    {
        private delegate void UpdateProgress(int percent);
        public Form1()
        {
            InitializeComponent();
        }

        private void btnCompute_Click(object sender, EventArgs e)
        {
            Thread thread = new Thread(new ThreadStart(doWork));
            thread.Start();
        }

        private void doWork()
        {
            for (int i = 1; i <= 100; i++)
            {
                //progressBar1.BeginInvoke((Action)(() => { progressBar1.Value = i; }));
                //lblPercent.BeginInvoke((Action)(() => { lblPercent.Text = string.Format("{0}%", i); }));
                //if (i == 100)
                //{
                //    MessageBox.Show("数据处理完毕!");
                //}
                update(i);
                Thread.Sleep(100);
            }
        }

        private void update(int percent)
        {
            if (InvokeRequired)
            {
                this.Invoke(new UpdateProgress(update), percent);
            }
            else
            {
                progressBar1.Value = percent;
                lblPercent.Text = string.Format("{0}%", percent);
                if (percent == 100)
                {
                    MessageBox.Show("数据处理完毕!");
                }
            }
        }
    }

WPF中常用技术

WPF中引入了Dispatcher,常用来解决非ui线程中更新ui控件状态的问题。

/// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {
        private delegate void UpdateProgress(int percent);
        public MainWindow()
        {
            InitializeComponent();
        }

        private void BtnCompute_OnClick(object sender, RoutedEventArgs e)
        {
            Task task = new Task(DoWork);
            task.Start();
        }

        private void DoWork()
        {
            for (int i = 1; i <= 100; i++)
            {
                //Dispatcher.BeginInvoke((Action)(() =>
                //{
                //    progressBar1.Value = i;
                //    lblPercent.Content = string.Format("{0}%", i);
                //    if (i == 100)
                //    {
                //        MessageBox.Show("数据处理完毕!");
                //    }
                //}));
                Dispatcher.BeginInvoke(new UpdateProgress(Update), i);
                Thread.Sleep(100);
            }
        }

        private void Update(int percent)
        {
            progressBar1.Value = percent;
            lblPercent.Content = string.Format("{0}%", percent);
            if (percent == 100)
            {
                MessageBox.Show("数据处理完毕!");
            }
        }
    }
时间: 2024-08-18 10:49:37

多线程更新UI的常用方法的相关文章

Android多线程更新UI的方式

Android下,对于耗时的操作要放到子线程中,要不然会残生ANR,本次我们就来学习一下Android多线程更新UI的方式. 首先我们来认识一下anr: anr:application not reponse:应用程序无响应 主线程:UI线程 anr产生的原因:主线程需要做很多重要的事情,响应点击事件,更新ui,如果在主线程里面阻塞时间过久,应用程序就会无响应,为了避免应用程序出现anr,所有的耗时的操作,都应该放在子线程中执行. 认识了anr后,我们就来学习一下怎样在Android下开启多线程

拒绝卡顿——在WPF中使用多线程更新UI

有经验的程序员们都知道:不能在UI线程上进行耗时操作,那样会造成界面卡顿,如下就是一个简单的示例: ????public partial class MainWindow : Window????{????????public MainWindow()????????{????????????InitializeComponent();????????????this.Dispatcher.Invoke(new Action(()=> { }));????????????this.Loaded

富客户端 wpf, Winform 多线程更新UI控件

前言 在富客户端的app中,如果在主线程中运行一些长时间的任务,那么应用程序的UI就不能正常相应.因为主线程要负责消息循环,相应鼠标等事件还有展现UI. 因此我们可以开启一个线程来格外处理需要长时间的任务,但在富客户端中只有主线程才能更新UI的控件. 解决方法 简单的来说,我们需要从其他的线程来更新UI线程的控件,需要将这个操作转交给UI线程(线程marshal). 方法1: 在底层的操作中,可以有以下的方法: WPF中,在element的Dispatcher类中调用BeginInvoke或者I

多线程更新ui

dispatch_async( dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0) , ^{ ..... dispatch_async(dispatch_get_main_queue(), ^{ [self createData]; NSIndexSet *index = [NSIndexSet indexSetWithIndex:1]; [_tableView reloadSections:index withRowAni

【基础】多线程更新窗体UI的若干方法

一.前言 在单线程中设置窗体某个控件的值很简单的事,只需要设置控件文本的值就可以了,但是有的业务场景很是复杂,界面上的控件也很多,这种情况下当数据量比较多的时候,在单线程中更新UI不可避免地会发生假死或卡顿现象,用户体验十分不爽,所以必须采用多线程来处理数据和UI.但是如果直接添加一个线程来更新控件信息,就会抛出错误,很显然微软并不希望我们这样做,因为UI控件不是线程安全的,如果随意地在任何线程中改变控件的值,会发生各种奇怪的问题,多个线程间会争夺资源,没有秩序地更改控件的值,显然这是我们不想看

Winform实现多线程异步更新UI(进度及状体信息)

引言 在进行Winform程序开发需要进行大量的数据的读写操作的时候,往往会需要一定的时间,然在这个时间段里面,界面ui得不到更新,导致在用户看来界面处于假死的状态,造成了不好的用户体验.所以在大量数据操作的应用上,需要使用多线程来处理这种情况.在c#中使用多线程很方便只需要使用System.Threading.Thread的一个实例的Start方法就行了,但是如何实现多线程之间的交互就不是那么简单.本文实现了用子线程去处理数据,并实时更新主线程的ui状态了.下面就开始一步步的去实现异步线程更新

Winform实现多线程异步更新UI(进度及状态信息)

引言 在进行Winform程序开发需要进行大量的数据的读写操作的时候,往往会需要一定的时间,然在这个时间段里面,界面ui得不到更新,导致在用户看来界面处于假死的状态,造成了不好的用户体验.所以在大量数据操作的应用上,需要使用多线程来处理这种情况.在c#中使用多线程很方便只需要使用System.Threading.Thread的一个实例的Start方法就行了,但是如何实现多线程之间的交互就不是那么简单.本文实现了用子线程去处理数据,并实时更新主线程的ui状态了.下面就开始一步步的去实现异步线程更新

(转).NET 4.5中使用Task.Run和Parallel.For()实现的C# Winform多线程任务及跨线程更新UI控件综合实例

http://2sharings.com/2014/net-4-5-task-run-parallel-for-winform-cross-multiple-threads-update-ui-demo 在C# WINFORM的开发中,难免会遇到多线程的开发以提高程序的执行效率.自己刚才开始在做多线程的开发时也遇到了很多这方面的问题,比如:如何使用并实现多线程功能.跨线程更新UI控件等问题.还记得最初使用的是System.Threading命名空间下的Thread类来实现的: C# 1 2 3

更新ui常用方法

更新ui代码段在Main线程执行常用方法 1.runOnUiThread 2.view.post view.postDelay() 3.handler.post handler.postDelay()