之前有个报表的程序,其中有一张报表速度比较慢。所以就加了个多线程。代码大致如下,有个query函数,然后我加了个thread指向他  tempt = new Thread(new ThreadStart(Query)); query函数里面是个while循环,
如下,其中根据 combo_ReportType的值 去做case when代码如下 
 while (true)
            {
                btn_query.Enabled = false;
                this.dgv_Report.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;
                String ReportSql = string.Empty;
                switch (combo_ReportType.Text)
                {
                    case "":
                        MessageBox.Show("请选择一个确定的报表!");
                        break;
                    case "急诊就诊量统计":
                        ReportSql = "ReportEmergencyMentimes " + dt_Start.Value.Year.ToString();
                        break;
                    case "急诊就诊量统计按日统计":
                        ReportSql = "ReportEmergencyMentimesByDays " + dt_Start.Value.Year.ToString() + "," + dt_Start.Value.Month.ToString();
                        break;
                    case "急诊留观病人信息表":
                        ReportSql = "OutComeReport " + SqlProcess.SqlProcess.Blank(dt_Start.Value.ToShortDateString()) + "," + SqlProcess.SqlProcess.Blank(dt_End.Value.AddDays(1).ToShortDateString());
                        break;
                    case "急诊死亡病人信息表":
                        this.dgv_Report.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells;
                        ReportSql = "DeathReport " + SqlProcess.SqlProcess.Blank(dt_Start.Value.ToShortDateString()) + "," + SqlProcess.SqlProcess.Blank(dt_End.Value.AddDays(1).ToShortDateString());
                        break;
                    case "急诊留观汇总报表":
                        ReportSql = "OutComeReportHZ " + SqlProcess.SqlProcess.Blank(dt_Start.Value.ToShortDateString()) + "," + SqlProcess.SqlProcess.Blank(dt_End.Value.AddDays(1).ToShortDateString());
                        break;
                    default:
                        break;                }
                if (String.IsNullOrEmpty(ReportSql) == false)
                {
                    RefreshGrid(ReportSql, "");
                }
              
                if (dgv_Report.Columns.Contains("deptid"))
                {
                    dgv_Report.Columns["deptid"].Visible = false;
                }
                if (dgv_Report.Columns.Contains("regid"))
                {
                    dgv_Report.Columns["regid"].Visible = false;
                }
                if (dgv_Report.Columns.Contains("cardid"))
                {
                    dgv_Report.Columns["cardid"].Visible = false;
                }
                if (dgv_Report.Columns.Contains("pid"))
                {
                    dgv_Report.Columns["pid"].Visible = false;
                }
                btn_query.Enabled = true;
                tempt.Suspend();
 
            }
while循环的最后我会suspend();然后 有个专门的按钮,我点击之后 会让线程resume,这样的话又会重新执行while循环 。button里面的代码是 
  if (tempt.ThreadState == ThreadState.Suspended)
                    tempt.Resume();
                else
                    tempt.Start();
个人感觉应该逻辑上没有什么问题,但是现在就是当combobox的值是“急诊留观病人信息表”的时候,窗体就会直接卡死。
但是请注意,我这段逻辑代码不用多线程的时候完全没有问题。而且case的差别不过是datagridview绑定的那个sql语句的不同。每句sql语句都能执行无误。
所以就觉得非常的奇怪,现在只好把这个case的情况拉到多线程外面去执行,也没有问题。大家说,这个问题大概是什么原因造成的            多线程bugdatagridviewthread

解决方案 »

  1.   

    补充 :   RefreshGrid(ReportSql, "");只是把sql绑定到datagridview的datasource而已。
      

  2.   

    代码有问题和对线程基本知识了解不够,不是C#Bug。
    1、多线程安全访问控件;
    2、一个线程只会启动一次,中途可暂停(通常人为阻塞或等待信号),但运行完后也就结束了;
    3、你要实现多线程暂停或继续应该使用线程同步或信号,这方面有很多资料的。
    4、?
      

  3.   

    1.我已经 CheckForIllegalCrossThreadCalls = false;这句话了,所以应该不存在多线程访问控件的问题
    2。我那个线程也只启动一次 。由于是while循环,所以从来没结束过。我只是中途认为的suspend和resume
      

  4.   

    CheckForIllegalCrossThreadCalls = false
    并不会对你的多线程有任何改善,而且也不推荐这么做。它一样会造成主界面阻塞。
      

  5.   

    http://201211131343.iteye.com/blog/1828965http://smycll.blog.163.com/blog/static/123739963201322782618719/http://msdn.microsoft.com/zh-cn/library/system.threading.thread.suspend.ASPX
    不要使用 Suspend 和 Resume 方法来同步线程的活动。 您无法知道挂起线程时它正在执行什么代码。 如果您在安全权限评估期间挂起持有锁的线程,则 AppDomain 中的其他线程可能被阻止。 如果您在线程正在执行类构造函数时挂起它,则 AppDomain 中尝试使用该类的其他线程将被阻止。 这样很容易发生死锁。 
      

  6.   

    六楼说的很有道理,以前只是看微软提示 不建议使用 Suspend 和 Resume ,这下有点知道为啥了.