注册 登录
编程论坛 VB.NET论坛

多线程读取PLC地址位数据导致主页面假死

无聊时想想你 发布于 2017-07-14 14:59, 3114 次点击
最近在学习多线程,所以DEMO了一个程式但主页面卡死,感觉3个现场都调用同一个PLC控件的原因导致的,求高手帮解
Imports ACTETHERLib
Imports System.Threading.Thread


Public Class Form1
    Private thread1, thread2, thread3 As Threading.Thread
    Public Delegate Sub MyDelegate()
    Public clsPlcComm As New ActQJ71E71TCP
    Public Declare Function GetPrivateProfileString Lib "kernel32" Alias "GetPrivateProfileStringA" (ByVal lpApplicationName As String, ByVal lpKeyName As String, ByVal lpDefault As String, ByVal lpReturnedString As String, ByVal nSize As Integer, ByVal lpFileName As String) As Integer
    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Try
            Dim PlcIp As String
            Dim PlcNetNo As String
            Dim PlcStatNo As String
            Dim PcNetNo As String
            Dim PcStatNo As String
            Dim TimeOut As String
            Dim dlen As String
            Dim str As String = New String(Chr(0), 1024)
            Dim lRet As Integer
            Dim rtnCode As String
            Dim inFilepath As String = Application.StartupPath & "\Plcsetting.ini"
            dlen = GetPrivateProfileString("PLC", "PLCIP", "", str, Len(str), inFilepath)
            PlcIp = Strings.Left(str, dlen)
            dlen = GetPrivateProfileString("PLC", "PlcNetNo", "", str, Len(str), inFilepath)
            PlcNetNo = Strings.Left(str, dlen)
            dlen = GetPrivateProfileString("PLC", "PlcStatNo", "", str, Len(str), inFilepath)
            PlcStatNo = Strings.Left(str, dlen)
            dlen = GetPrivateProfileString("PLC", "PcNetNo", "", str, Len(str), inFilepath)
            PcNetNo = Strings.Left(str, dlen)
            dlen = GetPrivateProfileString("PLC", "PcStatNo", "", str, Len(str), inFilepath)
            PcStatNo = Strings.Left(str, dlen)
            dlen = GetPrivateProfileString("PLC", "TimeOut", "", str, Len(str), inFilepath)
            TimeOut = Strings.Left(str, dlen)
            With clsPlcComm
                .ActHostAddress = PlcIp
                .ActNetworkNumber = PlcNetNo
                .ActStationNumber = PlcStatNo
                .ActSourceNetworkNumber = PcNetNo
                .ActSourceStationNumber = PcStatNo
                .ActTimeOut = TimeOut
            End With

            lRet = clsPlcComm.Open()
            If lRet = 0 Then
                lblPlcStatus.BackColor = Color.Green

            Else
                rtnCode = (String.Format("0x{0:x8}", lRet)).ToUpper

                MessageBox.Show("连接失败(出错代码 :" + rtnCode + ")")
                lblPlcStatus.BackColor = Color.Red

            End If
        Catch ex As Exception
            Throw New Exception(ex.Message, ex)
        End Try
    End Sub

    Public Sub handle1()
        Control.CheckForIllegalCrossThreadCalls = False
        Dim Devlist1 As String
        Dim lret As Integer
        Dim lData As Integer = 0
        Devlist1 = "ZR24024"
        Dim OldValue As Integer = 0

        While True
            Application.DoEvents()
            OldValue = lData
            lret = clsPlcComm.GetDevice(Devlist1, lData)
            If lData = OldValue Then

            Else
                ListBox1.Items.Add(lData)
                ListBox1.Refresh()
            End If
        End While
    End Sub

    'Me.BeginInvoke(New MyDelegate(AddressOf Getval))


    Public Sub handle2()
        Control.CheckForIllegalCrossThreadCalls = False
        Dim Devlist2 As String
        Dim lret As Integer
        Dim lData As Integer
        Devlist2 = "ZR2000"
        Dim OldValue As Integer = 0
        While True
            Application.DoEvents()
            OldValue = lData
            lret = clsPlcComm.GetDevice(Devlist2, lData)
            If lData = OldValue Then

            Else
                ListBox2.Items.Add(lData)
                ListBox2.Refresh()
            End If
        End While
    End Sub
    Public Sub handle3()
        Control.CheckForIllegalCrossThreadCalls = False
        Dim Devlist3 As String
        Dim lret As Integer
        Dim lData As Integer
        Devlist3 = "ZR1000"
        Dim OldValue As Integer = 0
        While True
            Application.DoEvents()
            OldValue = lData
            lret = clsPlcComm.GetDevice(Devlist3, lData)
            If lData = OldValue Then

            Else
                ListBox3.Items.Add(lData)
                ListBox3.Refresh()
            End If
        End While

    End Sub

    Private Sub btnMonitor_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnMonitor.Click
        btnMonitor.Enabled = False
        Application.DoEvents()
        thread1 = New Threading.Thread(AddressOf handle1)
        thread1.Start()
        thread2 = New Threading.Thread(AddressOf handle2)
        thread2.Start()
        thread3 = New Threading.Thread(AddressOf handle3)
        thread3.Start()
    End Sub

    'Public Sub Getval()
    '    Dim Devlist1 As String
    '    Dim lret As Integer
    '    Dim lData As Integer = 0
    '    Devlist1 = "ZR24024"
    '    Dim OldValue As Integer = 0

    '    While True
    '        Application.DoEvents()
    '        OldValue = lData
    '        lret = clsPlcComm.GetDevice(Devlist1, lData)
    '        If lData = OldValue Then

    '        Else
    '            ListBox1.Items.Add(lData)
    '            ListBox1.Refresh()
    '        End If
    '    End While
    'End Sub

End Class
3 回复
#2
shsmhq2017-07-15 11:31
While True 是死循环。

下面要加Thread.Sleep(200)大于100毫秒也会好一些。
#3
无聊时想想你2017-07-18 09:05
回复 2楼 shsmhq
不行,那个我有试过,加的时间长,会好些,到也有点卡,而且我要实时监控Plc值加了意义不大
#4
sjbandmm2017-12-08 22:08
多线程读取同一台设备只会效率更低,因为接口一个,还要不停的更换处理对象,造成处理更慢,因此正确的做法是用一个线程专门负责通讯,其他线程可以处理数据。
1