要提高界面的响应特性,最好的办法莫过于使用多线程,并把呈现界面的线程独立出来。以前只有使用C++才能实现的多线程功能,现在在.Net框架下,所有的语言(包括VB)都可以使用了。不过,使用多线程比使用单一线程要麻烦得多,比如线程之间的同步问题,做得不好很容易出错,而有的时候这种错误要开发人员花上几个星期的时间才能找到。在Windows Form软件中使用多线程更是有一些限制。
0. 在主程序执行一些长时间的耗时操作时候,(比如很多次的循环for(,,), 或者Thread.Sleep(xxx)), UI会没有反应。(因为窗口处理事件是按照消息队列中的顺序来的,没有处理到的就会带在队列里面,其中可能包括界面重绘即响应事件)。
1. 需要提高界面响应,可以使用新的线程来做一些耗时的操作,同时界面保持响应。
2. 耗时操作完成后,使用Control.Invoke/BeginInvoke来更新界面,有同步和异步两个方式,InvokeRequired是用来判断是否需要线程切换(Invoke实际上是把代码切换到主线程,也就是界面线程上面去执行)
3.搞清楚代码到底是在哪个线程上面执行。在new Thread()里面的代码都是在另外的线程上执行
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;
}
}
}