多线程耗时操作及界面更新

要提高界面的响应特性,最好的办法莫过于使用多线程,并把呈现界面的线程独立出来。以前只有使用C++才能实现的多线程功能,现在在.Net框架下,所有的语言(包括VB)都可以使用了。不过,使用多线程比使用单一线程要麻烦得多,比如线程之间的同步问题,做得不好很容易出错,而有的时候这种错误要开发人员花上几个星期的时间才能找到。在Windows Form软件中使用多线程更是有一些限制。


0. 在主程序执行一些长时间的耗时操作时候,(比如很多次的循环for(,,), 或者Thread.Sleep(xxx)), UI会没有反应。(因为窗口处理事件是按照消息队列中的顺序来的,没有处理到的就会带在队列里面,其中可能包括界面重绘即响应事件)。

1. 需要提高界面响应,可以使用新的线程来做一些耗时的操作,同时界面保持响应。

2. 耗时操作完成后,使用Control.Invoke/BeginInvoke来更新界面,有同步和异步两个方式,InvokeRequired是用来判断是否需要线程切换(Invoke实际上是把代码切换到主线程,也就是界面线程上面去执行)

3.搞清楚代码到底是在哪个线程上面执行。在new Thread()里面的代码都是在另外的线程上执行

1.Form1.cs

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;

namespace UpdateUITest
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            string mnem = this.textBox1.Text.Trim();
            //string price = GetPriceUsingNewThread(mnem);
            GetPriceUsingNewThread(mnem);
        }

        private void GetPriceUsingNewThread(string mnem)
        {
            string price = ServiceProvider.GetPrice2(mnem);
        
            this.textBox2.Text = price;
        }

        private void GetPriceUsingNewThread2(string mnem)
        {
            string price = string.Empty;

            new Thread(()=>
            {
                price = ServiceProvider.GetPrice(mnem);
                if (this.InvokeRequired)
                {
                    this.Invoke(new Action(() =>
                        {
                            this.textBox2.Text = price;
                        }));
                }
                else
                {
                    this.textBox2.Text = price;
                }
            }).Start();
        }

        private void GetPriceUsingNewThreadInLamda(string mnem)
        {
            string price = string.Empty;
            bool hasGotValue = false;

            new Thread(()=>
            {
                price = ServiceProvider.GetPrice(mnem);
                hasGotValue = true;
            }).Start();

            while (!hasGotValue)
            {
                Application.DoEvents();
            }

            this.textBox2.Text = price;
        }
    }
}



2. ServiceProvider.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace UpdateUITest
{
    class ServiceProvider
    {
        public static string GetPrice(string mnem)
        {
            string resultPrice;

            if (mnem.ToUpper() == "IBM")
            {
                resultPrice = "10.00";
            }
            else
            {
                resultPrice = "20.00";
            }

            System.Threading.Thread.Sleep(9000);

            return resultPrice;
        }

        public static string GetPrice2(string mnem)
        {
            string resultPrice;

            if (mnem.ToUpper() == "IBM")
            {
                resultPrice = "10.00";
            }
            else
            {
                resultPrice = "20.00";
            }

            //If you are doing something which would last a long time
            //,please give main thread(UI thread) a chance to update itself every other few miliseconds.
            for (int i = 0; i < 5000; i++)
            {
                Application.DoEvents();
                System.Threading.Thread.Sleep(2);
            }

            return resultPrice;
        }
    }
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值