本帖最后由 GUNDAM525 于 2010-01-07 12:39:30 编辑

解决方案 »

  1.   

      private void SetDataGridView()   //控件操作   
            { lock (this)
                    {            DataViewsSet = oraCls.createView(dateTimePicker1.Value.ToString("yyyyMMdd"), dateTimePicker2.Value.ToString("yyyyMMdd"), myFilter());//, bindingNavigator1);            DataViews.AutoGenerateColumns = true;
                DataViews.DataSource = DataViewsSet.Tables[0];
                for (int i = 0; i < DataViews.Columns.Count; i++)
                {
                    DataViews.Columns[i].HeaderCell.Style.WrapMode = DataGridViewTriState.False;
                }            //将字段名写入listBox
                for (int j = 0; j < DataViews.ColumnCount; j++)
                    LstBx_All.Items.Add(DataViews.Columns[j].Name);            DataViews.Refresh();
                LB_Count.Text = "记录数:" + (DataViews.RowCount - 1).ToString();
            }
    }
      

  2.   

    你这线程跟没用一样,这里的委托里的代码是和form主线程同步的,要在线程里循环
      

  3.   

    是吧,我对线程还没有太多的了解,但是客户要求查询数据时datagridview不要在那里假死把整个程序给卡着动不了。
    实际上,我这段代码主要的是 DataViewsSet = oraCls.createView(dateTimePicker1.Value.ToString("yyyyMMdd"),dateTimePicker2.Value.ToString("yyyyMMdd"), myFilter
             DataViews.AutoGenerateColumns = true; 
             DataViews.DataSource = DataViewsSet.Tables[0];             for (int i = 0; i < DataViews.Columns.Count; i++) 
                { 
                    DataViews.Columns[i].HeaderCell.Style.WrapMode = DataGridViewTriState.False; 
                }             //将字段名写入listBox 
                for (int j = 0; j < DataViews.ColumnCount; j++) 
                    LstBx_All.Items.Add(DataViews.Columns[j].Name);             DataViews.Refresh(); 
                LB_Count.Text = "记录数:" + (DataViews.RowCount - 1).ToString(); 
    就是用datatable把数据库中的数据取出来放在grid里面,请问该如何做呢
      

  4.   

    帮你简单改了下 把多线程改成异步 
    你自己测试看看#region 用多线程测试
            delegate void SetVisibleDelegate();
            Thread DataViewsThread;
            DataSet DataViewsSet = new DataSet();
            //private void BindThread()
            //{
            //    //Control.CheckForIllegalCrossThreadCalls = false;
            //    ThreadStart bind = new ThreadStart(SetDataGridView);
            //    DataViewsThread = new Thread(bind);
            //    DataViewsThread.Start();
            //}        private void CheckIsIn()
            {
                SetVisibleDelegate mDelegate = new SetVisibleDelegate(()=>{DataViewsSet = oraCls.createView(dateTimePicker1.Value.ToString("yyyyMMdd"), dateTimePicker2.Value.ToString("yyyyMMdd"), myFilter());});
                mDelegate.BeginInvoke(CallBack, null);
            }        private void CallBack(IAsyncResult ar)
            {
                if (ar == null)
                    return;
                if (ar.IsCompleted)
                {
                    if (this.InvokeRequired)
                    {
                        MethodInvoker mInvoker = new MethodInvoker(SetDataGridView);
                        this.Invoke(mInvoker, null);
                    }
                    else
                    {
                        SetDataGridView();
                    }
                }
            }
            private void SetDataGridView()   //控件操作   
            {            //DataViewsSet = oraCls.createView(dateTimePicker1.Value.ToString("yyyyMMdd"), dateTimePicker2.Value.ToString("yyyyMMdd"), myFilter());//, bindingNavigator1);            DataViews.AutoGenerateColumns = true;
                DataViews.DataSource = DataViewsSet.Tables[0];
                for (int i = 0; i < DataViews.Columns.Count; i++)
                {
                    DataViews.Columns[i].HeaderCell.Style.WrapMode = DataGridViewTriState.False;
                }            //将字段名写入listBox
                for (int j = 0; j < DataViews.ColumnCount; j++)
                    LstBx_All.Items.Add(DataViews.Columns[j].Name);            DataViews.Refresh();
                LB_Count.Text = "记录数:" + (DataViews.RowCount - 1).ToString();        }
    #endregion
      

  5.   

    谢谢,但是还是卡着不动了,我怀疑是不是datagridview自身对大量数据显示处理的问题,有没有办法让数据滚动式添加到datagridview中去呢?由于取出数据量稍微有点大,用户也知道他要查询的数据很多,需要时间处理,就是不能忍受界面卡着不动,呵呵
      

  6.   

    另外加个滚动条?已经在datagridview中设置了啊,scollbar=both,还要另外加一个?
      

  7.   

    显示的问题 你试试DataGridView虚拟模式虚拟模式是为使用大型数据存储区而设计的。当 VirtualMode 属性为 true 时,可以创建一个包含大量行和列的 DataGridView,然后处理 CellValueNeeded 事件来填充单元格。虚拟模式要求实现基础数据缓存,以便基于用户的操作来处理 DataGridView 单元格的填充、编辑和删除。(MSDN)
      

  8.   

    我遇到的情况跟你很相似,我的情况:1.主界面一开始运行就开启一个线程TempThread ,时刻监听本机端口(2000)收到的数据
              2.将数据转化翻译后,添加到DataGridView的列表里面
              3.由于我监听的是所有消防联网用户往监控中心上报的报警信息,数据很多
              4.出现的问题,我的DataGridView能一次显示30条信息,但是,一过30条,滚动条就假死,
                还不能去拉动滚动条,否则,整个程序会变成 未响应问题的已经解决。由于程序本身是一个线程,监听是一个线程,而线程之间的控件赋值就会报错,所以采用
    委托的办法解决。但是,我如楼主一样,之前的委托使得不对,滚动条照样假死。后来改成:       #region 构造函数
            public MainFrm()
            {
                InitializeComponent();             
                ThreadStart TS = new ThreadStart(this.StartReceive);//端口监听线程
                Thread TempThread = new Thread(TS);
                TempThread.IsBackground = true;//后台运行
                TempThread.Start();
            }
            #endregion  private void StartReceive()//端口监听线程
      {            
                    
        TcpListener server = new TcpListener(IPAddress.Parse(Operator.ServerIP),2000);               
         server.Start();//监听本机2000端口,收取报告
         MethodInvoker mi = new MethodInvoker(Add_Alarm);//声明委托,即往DataGridView添加行
         while (true)
         {
            TcpClient client = server.AcceptTcpClient();
            NetworkStream ns = client.GetStream();
            byte[] bytes = new byte[1024];
            int bytesread = ns.Read(bytes, 0, bytes.Length);
            msg = Encoding.Default.GetString(bytes, 0, bytesread);//监听到的数据
            if (msg != "")
            {
               Common.SysRun_Log(Operator.RunLogFpath, "系统监听到  " + msg);//运行日志
               this.BeginInvoke(mi);//执行委托
            }
            ns.Close();
            client.Close();
         }         
     }
     
             private void Add_Alarm() //将监听到的火警报告插入 DataGridView 
             { 
                msg = MainFrmB.Add_AlarmInfo(msg);
                Common.SysRun_Log(Operator.RunLogFpath, "消息格式化后  " + msg); //运行日志
                msg = msg.Insert(msg.LastIndexOf('|') + 1, "火警  ");
                this.dataGridView1.Rows.Insert(0, msg.Split('|'));//插入一行新的报告
                dataGridView1.Rows[0].DefaultCellStyle.BackColor = Color.Red;
              }希望能够帮到你    
      

  9.   

    你的说虚拟模式我也看过了,但是我还没有明白cellvalueneeded事件填充单元格到底是如何实现的,看了例子没太明白这个事件是怎么回事
      

  10.   

     MethodInvoker mi = new MethodInvoker(Add_Alarm);//声明委托,即往DataGridView添加行 我是采用c# winform 中MethodInvoker 委托类来处理我要操作控件的过程
     操作控件的过程都封装在Add_Alarm函数里面

      

  11.   

    谢谢,但是按照你的写法,datagridview在从datatable取值过程中,程序还是会假死。呵呵,我那个写法,至少在执行过程中,程序可以自由活动,只是到数据出来后,滚动条不能用罢了
      

  12.   

    这是我按照你的写法改的代码,但是执行时,界面仍会卡,我想是不是我数据太多,需要在datatable里做点处理啊   private void BTN_Login_Click(object sender, EventArgs e)
            {
                LB_Count.Text = "正在查询数据库……";
                DataViews.Columns.Clear();
                DataViews.Visible = true;//这个是我当前显示产品数据的grid
                PDSDataView.Visible = false; //一次只让一个grid显示在用户上
                FailCoilDataView.Visible = false;//这个和上面PDSDataView是用来做废品判断显示
                
                ThreadStart TS = new ThreadStart(this.ControlGrid);
                Thread TempThread = new Thread(TS);
                TempThread.IsBackground = true;//后台运行
                  TempThread.Start();             for (int i = 0; i < DataViews.Columns.Count; i++)
                 {
                     DataViews.Columns[i].HeaderCell.Style.WrapMode = DataGridViewTriState.False;
                 }             //将字段名写入listBox
                 for (int j = 0; j < DataViews.ColumnCount; j++)
                     LstBx_All.Items.Add(DataViews.Columns[j].Name);
            }private void ControlGrid()
            {
                MethodInvoker mi = new MethodInvoker(SetDataGridView);//声明委托,即往DataGridView添加行
                this.BeginInvoke(mi);
            }
            
            private void SetDataGridView()   //控件操作   
            {
                DataSet DataViewsSet = new DataSet();
                DataViewsSet = oraCls.createView(dateTimePicker1.Value.ToString("yyyyMMdd"), dateTimePicker2.Value.ToString("yyyyMMdd"), myFilter());            DataViews.DataSource = DataViewsSet.Tables[0];            LB_Count.Text = "记录数:" + (DataViews.RowCount - 1).ToString();
            }
      

  13.   

    能不能把 BTN_Login_Click(object sender, EventArgs e)中的     for (int i = 0; i < DataViews.Columns.Count; i++)
                 {
                     DataViews.Columns[i].HeaderCell.Style.WrapMode = DataGridViewTriState.False;
                 }             //将字段名写入listBox
         for (int j = 0; j < DataViews.ColumnCount; j++)
                  LstBx_All.Items.Add(DataViews.Columns[j].Name);
     
        剪切到 SetDataGridView() 的开头去,因为上面两段代码都是跨线程操作控件赋值,
        但这样修改后,不知是否会影响你的业务逻辑
      

  14.   


            private void DataViews_CellValueNeeded(object sender, DataGridViewCellValueEventArgs e)
            {
                e.Value = DataViewsSet.Tables[0].Rows[e.RowIndex][e.ColumnIndex];
            }
      

  15.   

    估计你的问题不在这里 我刚测试 4000行300列 所有cell值为26个字母 用DataSource绑定 显示很快
    毙掉DataViews.Refresh(); 试试