我要在一个线程里面对数据进行处理,处理完成后,在主线程进行界面刷新。为了使数据同步我用了AutoResetEvent,如下:
//成员变量
AutoResetEvent m_arePda =null;
//加载PDA文件线程
private void LoadPdaFileThread()
{
Thread.Sleep(10000); //模拟大数据加载 ..
m_arePda.Set();
}
private void Form1_Load(object sender, EventArgs e)
{
m_arePda = new AutoResetEvent(false); //创建非终止事件 Thread trd = new Thread(LoadPdaFileThread);
trd.Start(); m_arePdaList.WaitOne(); //开始将数据在界面显示
...
}问题:现在因为在FormLoad里面用到了m_arePdaList.WaitOne();这样的话,只有当线程执行完,主界面才能显示出来。我想要的是 显示主界面(没数据的)->线程加载数据->主界面显示数据 这样的流程我试过直接在线程里面刷新主界面,不过那个局限性太大,刷一两个控件(如进度条)还没问题,不过同时刷好几个控件的话(如在ListView加数据,又要改变按钮状态,又改变窗口提示文字等)要写很多委托。所以就想先把数据加完,再刷界面。请.NET牛人们不吝赐教。
//成员变量
AutoResetEvent m_arePda =null;
//加载PDA文件线程
private void LoadPdaFileThread()
{
Thread.Sleep(10000); //模拟大数据加载 ..
m_arePda.Set();
}
private void Form1_Load(object sender, EventArgs e)
{
m_arePda = new AutoResetEvent(false); //创建非终止事件 Thread trd = new Thread(LoadPdaFileThread);
trd.Start(); m_arePdaList.WaitOne(); //开始将数据在界面显示
...
}问题:现在因为在FormLoad里面用到了m_arePdaList.WaitOne();这样的话,只有当线程执行完,主界面才能显示出来。我想要的是 显示主界面(没数据的)->线程加载数据->主界面显示数据 这样的流程我试过直接在线程里面刷新主界面,不过那个局限性太大,刷一两个控件(如进度条)还没问题,不过同时刷好几个控件的话(如在ListView加数据,又要改变按钮状态,又改变窗口提示文字等)要写很多委托。所以就想先把数据加完,再刷界面。请.NET牛人们不吝赐教。
二、我在应用程序中用Shown试过了,效果不是很好。(我在线程加载数据时,会更新界面里的一个ProgressBar,可如果用Show事件后,进度条不到AutoResetEvent.set()后,它不会显示
我现在就是在线程里面把数据加载到一个List<string>里面,然后想主线程等子线程把数据加载完成后,把List显示出来,用Timer会不会太浪费了?因为随着线程的执行,我的List里面的数据越来越多,那用Timer定时显示时,肯定要先清空以前显示的,然后把List全部显示出来??这样~~~有点小恐怖。呵呵 对你的回答表示感谢。
应该用list1 = list2;list2是你线程里读取到的数据,这样只有你数据全部读取完全局的List才有数据,Timer才会显示
{
for (int i = 0; i < 10000; i++)
{
SetText(i.ToString(), DateTime.Now.ToString("hh:mm:ss ms"));
Thread.Sleep(100);
}
}
private void SetText(string text,string datetimes)
{
if (this.InvokeRequired)
{
this.Invoke(new SetTextCallback(SetText), new object[] {text,datetimes }); //
}
else
{ this.textBox1.Text = text; //记录当前值
this.txt_1_d2.Text = datetimes; //记录现在时间
}
}
private void fill_text2()
{
int i = 0;
while (i <= 20000)
{
SetText2(i.ToString(), DateTime.Now.ToString("hh:mm:ss ms"));
Thread.Sleep(100);
i++;
}
}
private void SetText2(string text, string datetimes)
{
if (this.InvokeRequired)
{
this.Invoke(new SetTextCallback(SetText2), new object[] { text, datetimes }); //
}
else
{
this.textBox2.Text = text; //记录当前值
this.txt_2_d2.Text = datetimes; //记录现在时间
}
}
不要用 WaitOne, 等数据加载完之后用 Control.BeginInvoke 或者 Control.Invoke. 那我用什么来等待数据加载完呢?
不过 一、我要显示的数据,不是显示时间这么简单。我必须要等子线程把数据加载成功后才显示。不然显示的内容肯定是不正确的。我的问题核心是“如何让主界面来等子线程结束,然后自己再把子线程计算的结果显示出来,在此过程中主界面是一直可以看到的。” 二、如果我在子线程中直接刷新界面。那就回到我的题目了:我试过直接在线程里面刷新主界面,不过那个局限性太大,刷一两个控件(如进度条)还没问题,不过同时刷好几个控件的话(如在ListView加数据,又要改变按钮状态,又改变窗口提示文字等)要写很多委托
阻塞主线程了
解决办法二:不用AutoResetEvent感觉有点画蛇添足,你开线程的原因就是要用来不使主界面阻塞
建议用backgroundworker组件,在dowork方法里取数据(这个方法里不能有对界面操作的代码),在completed事件里更新界面(事件名字可能不对,查查msdn吧)