vb.net 多线程 窗体 假死

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了vb.net 多线程 窗体 假死相关的知识,希望对你有一定的参考价值。

代码如下

代码如下:

Private Sub btnLogin_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnLogin.Click
Dim chkl As New Login
Dim th As New Threading.Thread(AddressOf chkl.ChkLogin)
chkl.UserName = UserName.Text.Trim.ToString
chkl.Pwd = Pwd.Text.Trim.ToString
th.Start()
UserName.Enabled = False
Pwd.Enabled = False
btnLogin.Enabled = False
LoginInfo.Text = "系统正在拉取用户数据,请稍后……"
End Sub

Delegate Sub SFM()
Sub ShowfrmMain()
If Me.InvokeRequired Then
Dim dh As New SFM(AddressOf ShowfrmMain)
Me.Invoke(dh)
Else
frmMain.Show()
Me.Close()
End If
End Sub

Class Login
Public UserName As String
Public Pwd As String

Function OpenDB()
Dim Conn As New OleDb.OleDbConnection("Provider=Microsoft.Jet.Oledb.4.0;Data Source=DataBase/DFZJOADB.MDB")
Try
Conn.Open()
Return Conn
Catch ex As Exception
Msg(ex.ToString)
End Try
End Function
Sub ChkLogin()
Dim sql As String = "select * from UserInfo where UserName='" & UserName & "'"
Dim DRL As New OleDbCommand(sql, OpenDB)
Dim ReadLoginData As OleDbDataReader = DRL.ExecuteReader()
ReadLoginData.Read()
If ReadLoginData.HasRows Then
If Pwd = ReadLoginData(2).ToString.Trim Then
System.Threading.Thread.Sleep(3000)
frmLogin.ShowfrmMain()
Else
Msg("您输入的密码错误!")
Exit Sub
End If
Else
Msg("没有该用户数据!")
Exit Sub
End If

End Sub
End Class

但是这样窗体就会假死,拖动不了,怎么解决这个问题呢?

并没有看出什么地方可能导致程序假死,这排版也太乱了.不妨调试一下程序,当出现你说的"假死"后暂停一下程序,看看线程都卡在哪里.
另外,从设计上来看,你这里并不需要多线程操作.
参考技术A System.Threading.Thread.Sleep(3000)本回答被提问者和网友采纳

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;
            }
        }

 




以上是关于vb.net 多线程 窗体 假死的主要内容,如果未能解决你的问题,请参考以下文章

vb.net 线程托管 窗口假死

vb.net多线程,循环导致窗口界面假死的问题

VB.NET程序界面假死如何解决

VB.net可以多线程控制同一个窗体及其控件吗

winform 利用 多线程 处理窗体假死,利用 Invoke BeginInvoke 处理子线程调用 UI 控件报错的问题

我用C# winform多线程,窗口就假死,等到线程全部完成了才可以点击。请问要怎么才可以让窗口不假死。