点击进入winfrom窗体时因为窗体需要加载数据比较耗时会出现窗体假死,这个怎麼用多线程解决?

我需要的是先把窗体加载出来再加载数据,这样效果会好一点,不知是否用多线程可以解决,我需要源码

private void Form1_Load(object sender, EventArgs e)
{
    //可以设置一个lable,背景为一个动态图片,例如:loading....
       
    Thread td = new Thread(new ThreadStart(LoadData));
    td.IsBackground = true;
    td.Start();
}
void LoadData()
{
    //模拟加载数据的时间
    Thread.Sleep(1000*5);
    this.BeginInvoke(new MethodInvoker(delegate() {
       
        //数据加载完成后,控制lable隐藏代码
        //..................
    }));
}

追问

stringstrSql=”这里抓10万条数据”;
dataGridView1.DataSource = dbAccess.ExecuteDataSet(strSql,CommandType.Text,null).Tables[0];//这里通过调用封装好的方法返回一个datatable数据源给dataGridView1
重点:这里因为涉及到窗体的dataGridView1,所以抓数据界面会卡,所以这个线程该如何写

追答

上面的代码不能解决你的问题嘛?你把Thread.Sleep(1000*5);换成你取数据加载的过程不就可以了嘛。

追问

非常感谢,我找到我的出错问题,工作线程在请求数据(耗时操作)的时候UI线程也在执行数据库相关操作,导致了数据库打开关闭异常。
我还想问一个问题,就是工作线程在请求数据的时候,我点击窗体的一些单选按钮(未促发事件)会卡死,等待数据请求完毕之後窗体就可正常工作,那有什麽方法可以避免窗体卡死吗?我感觉问得比较多.....

追答

你已经利用线程异步操作了,怎么会卡死,这两者是不会相互干预的啊。
除非你的code逻辑有问题

追问

卡死是因为下面的代码:
this.BeginInvoke(new MethodInvoker(delegate()
{
this.dataGridView1.DataSource = dtthread;
}
因为工作线程请求的数据是传给了控件(datagridview),所以相当於又启用了UI线程然後介面就会在请求数据的时候因为窗体是未完全加载(加载控件)完毕的所以导致了窗体假死

追答

你十来W的数据一定性加载到Grid上了?????
你不搞个分页什么的?

追问

没弄过,大神求教,分页是用存储过程还是什麽?

追答

这种量级不需要存储过程哦,DataGridView自带有分页功能,你百度下就知道了,设置下的事。

追问

太感谢了,3Q
这个在数据库请求数据弄一个进度条,请求数据的时候显示进度条,数据请求完毕进度条消失这个可以写在请求数据的线程裏面吗?

追答

进度条在窗体上,控制进度条前近的过程可以写在线程里面,记得用异步,不然访问会报错。

追问

我的想法是把进度条相关代码写在下面的大括号里,这样可行吗?
this.BeginInvoke(new MethodInvoker(delegate()
{
this.dataGridView1.DataSource = dtthread;
}

追答

这个代码是结束后用的吧。。。

追问

那我如何实现进度条功能呢?请求数据的时候开启请求完毕关闭进度条,实时更新进度条

追答

时时更新过程需要你操作你的数据加载流程的,比如请求算一步,获取算一步,加载 算一步,
每一部都用异步更新进度条就行了。

温馨提示:答案为网友推荐,仅供参考
第1个回答  2013-05-06
用多线程,或线程池来加载数据就好了

ThreadPool.QueueUserWorkItem(
new WaitCallback(obj =>
{

加载数据的代码。。。。。
加载完成后把界面上的进度条什么的隐藏起来,再显示原有界面

})
);

个人感觉用WPF来写会好一点,因为WPF是以数据来驱动的,而Winfrom是事件驱动追问

stringstrSql=”这里抓10万条数据”;
dataGridView1.DataSource = dbAccess.ExecuteDataSet(strSql,CommandType.Text,null).Tables[0];//这里通过调用封装好的方法返回一个datatable数据源给dataGridView1
重点:这里因为涉及到窗体的dataGridView1,所以抓数据界面会卡,所以这个线程该如何写

追答

你可以先定义一个bool属性
private bool loadOver;

public bool LoadOver
{
get { return loadOver; }
set {
loadOver = value;
if(loadOver)//当loadOver为真时
{
这里加载你的窗口界面代码
}
}
}

public void Methed()
{
loadOver=false;
ThreadPool.QueueUserWorkItem(
new WaitCallback(obj =>
{

stringstrSql=”这里抓10万条数据”;
dataGridView1.DataSource = dbAccess.ExecuteDataSet(strSql,CommandType.Text,null).Tables[0];
loadOver=true;//给loadOver赋值时可以在属性代码中再加窗口加载的代码

})
);

}

相似回答