zoukankan      html  css  js  c++  java
  • winform 利用 多线程 处理窗体假死,利用 Invoke BeginInvoke 处理子线程调用 UI 控件报错的问题

    因为工作需要自己写了一个简单的工具软件,数据库查询每日OA未发送成功流程的日志记录以及批量重处理操作。

    开始使用的是单线程,后台查询数据库的时候窗体假死,使用多线程很简单就能解决。

            private void btnQuey_Click(object sender, EventArgs e)
            {
                this.button2.Enabled = false;
                Thread connectionThread = new Thread(new ThreadStart(connectDB));
                connectionThread.Start();
            }

    接下来的问题就比较棘手,因为我在子线程中会调用UI控件,这个时候多次点击查询(调用子线程)就会报错,刚遇见的时候真的没有思路,后来网上无意中看到一篇文章写Invoke和BeginInvoke的(http://www.cnblogs.com/worldreason/archive/2008/06/09/1216127.html),文章很好,而且恰好就能解决我的问题。原来是windows程序消息机制的问题,子线程如果直接调用UI控件就会影响这个机制。

    delCheckEnvironment委托是用来检查查询环境是否选择,如果选择了才能继续往下执行子线程,有先后关系,所以使用Invoke把delCheckEnvironment封送到主线程执行,阻塞子线程往下执行,直到封送的委托被主线程执行完毕。
    而下面的BeginInvoke(delUpdateGridView,ds)就不需要阻塞子线程,让主线程的GridView显示数据集的时候子线程也执行,不需要区分先后顺序。


            private void connectDB()
            {
    
                DelCheckEnvironment delCheckEnvironment = new DelCheckEnvironment(CheckEnvironment);
                
                Invoke(delCheckEnvironment);
    
                DateTime startTime = this.dateTimePicker1.Value;
                DateTime endTime = this.dateTimePicker2.Value;
    
                string st = startTime.ToString("yyyy-MM-dd 00:00:00 000");
                string st1 = (startTime + TimeSpan.FromDays(1)).ToString("yyyy-MM-dd 00:00:00 000");
                string ed = endTime.ToString("yyyy-MM-dd 00:00:00 000");
                string ed1 = (endTime + TimeSpan.FromDays(1)).ToString("yyyy-MM-dd 00:00:00 000");
                string sql = "select distinct SendDH,Taskid,Returnmsg from AYS_Process_Log where SendTime >='" + st + "' and SendTime <'" + st1 + "' and Returnmsg not like '%成功%' and Returnmsg not like  '%已接收%' and Returnmsg not like '%{"data":{},"returncode":"0"}%'  and Returnmsg <> '' and Returnmsg not like '%"ZSTS":1%' and Returnmsg not like '%OA单号在SAP系统内已存在%' and Taskid not in "
                             + "(select distinct Taskid from Process_Log where (SendTime >='" + st + "' and SendTime <'" + ed1 + "') and(Returnmsg like '%成功%' or Returnmsg like  '%已接收%' or Returnmsg like '%{"data":{},"returncode":"0"}%'  or Returnmsg = '' or Returnmsg like '%"ZSTS":1%' or Returnmsg like '%OA单号在SAP系统内已存在%'))";
    
                DataSet ds = new DataSet();
                try
                {
                    using (SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings[sqlIp].ConnectionString.ToString()))
                    {
                        using (SqlCommand cmd = new SqlCommand(sql, conn))
                        {
                            cmd.CommandTimeout = 80000;
                            using (SqlDataAdapter da = new SqlDataAdapter(cmd))
                            {
                                da.Fill(ds, "Process_Log");
                            }
                        }
                    }
                DelUpdateGridView delUpdateGridView = new DelUpdateGridView(updateGridView);
                BeginInvoke(delUpdateGridView,ds);
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.ToString());
                }
                
            }
            private void updateGridView(DataSet ds)
            {
                if (ds.Tables[0].Rows.Count > 0)
                {
                    this.dataGridView1.DataSource = ds;
                    this.dataGridView1.DataMember = "AYS_Process_Log";
                    dataGridView1.Columns[0].HeaderText = "OA单号";
                    dataGridView1.Columns[0].Width = 120;
                    dataGridView1.Columns[1].HeaderText = "TaskId";
                    dataGridView1.Columns[1].Width = 50;
                    dataGridView1.Columns[2].HeaderText = "接口返回信息";
                    dataGridView1.Columns[2].Width = 1000;
                }
                else
                {
                    MessageBox.Show("未查询到失败单号");
                }
                this.btnQuery.Enabled = true;
            }
    
            public void CheckEnvironment()
            {
                if (checkEnviroment())
                {
                    MessageBox.Show("请选择环境");
                    this.btnQuery.Enabled = true;
                    return;
                }
            }
  • 相关阅读:
    高效并发服务器模型
    Linux下Wiki服务器的搭建
    Wiki程序PmWiki的安装和汉化
    Linux 套接字编程中的 5 个隐患
    IOCP简介
    IP协议详解之IP地址要领
    IP协议详解之配套协议:ARP, ICMP
    超级详细Tcpdump 的用法
    如何测试主机的MTU多大?
    Linux下Socket编程的端口问题( Bind error: Address already in use )
  • 原文地址:https://www.cnblogs.com/KSalomo/p/6524958.html
Copyright © 2011-2022 走看看