как использовать последовательный порт в среде приложения-службы, постоянно прослушивая данные - PullRequest
0 голосов
/ 19 сентября 2018

Я написал сервисное приложение, которое прослушивает порт для любых сообщений, которые могут возникнуть, наша лаборатория будет запускать определенный тест, который будет посылать последовательные данные каждые пару часов или около того.служба работает, забирает данные в течение нескольких часов, а затем загадочным образом останавливается.системный журнал событий сообщает, что служба неожиданно прервана.и в журнале событий приложения имеется более описательная ошибка .NET:

Приложение: BondTestService.exe Framework Версия: v4.0.30319 Описание: Процесс был прерван из-за необработанного исключения.Информация об исключении: System.ObjectDisposedException в System.Runtime.InteropServices.SafeHandle.DangerousAddRef (Boolean ByRef) в System.StubHelpers.StubHelpers.SafeHandleAddRef (System.Runtime.InteropServices.SafeHandNoef.Ogn.Og.RegSlayEngEnt_RegSlayEnt_RegSlaySlaySlaySlaySlaySlaySlaySlaySlaySlaySlaySlaySlaySlaySlaySlaySignSLR)..Win32.SafeHandles.SafeFileHandle, System.Threading.NativeOverlapped *, Int32 ByRef, Boolean) в System.IO.Ports.SerialStream + EventLoopRunner.WaitForCommEvent () в System.Threading.ThreadHelper.Thread System.Oject.ExecutionContext.RunInternal (System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean) в System.Threading.ExecutionContext.Run (System.Threading.ExecutionContext, System.Threading.ContextCallback, Boo.Object.в System.Threading.ExecutionContext.Run (System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object) в System.Threading.ThreadHelper.ThreadStart ()

я былчитая, как сервисы ведут себя и как ведут себя последовательные порты, так что поправьте меня, если я ошибаюсь, если между тестами есть промежуток в 2 часа или около того, сервис предположит, что он не работает, и сам остановится?

Я также прочиталпосле чтения буфера из последовательного порта я добавляю к объекту строителя строк, как показано ниже, и делаю то, что мне нужно со строкой, а затем, что происходит с последовательным портом, остается ли он открытым в ожидании следующего значения или мне нужно закрыть его иоткрыть его, чтобы обновить?

Не уверен, как с этим справиться, так как он должен быть открыт, ожидая, что тестировщик лаборатории отправит свои данные в любой момент времени.

Imports System
Imports System.Data.SqlClient
Imports System.IO.Ports
Imports System.Net.Mime
Imports Microsoft.Win32
Imports System.IO
Imports System.Text.RegularExpressions
Imports BondTestService.PI
Imports PCA.Core.Configuration

Public Class Bond
Dim WithEvents serialPort As New IO.Ports.SerialPort
Public Delegate Sub myDelegate()
Public RawString As New System.Text.StringBuilder
Public value As String
Public BondTest As Integer = 10

 #Region "Commport Traffic and Configuration Validations"
 Public Sub StartListening()

    If serialPort.IsOpen Then
        serialPort.Close()
        ErrorLog2(Now.ToString & "Port Closed because StartListening method started over")
    End If

    Try
        With serialPort
            .PortName = Registry.LocalMachine.OpenSubKey("SOFTWARE\Wow6432Node\AUTOLABDEVICESERVICE\bondtest", True).GetValue("commport")
            .BaudRate = CInt(Registry.LocalMachine.OpenSubKey("SOFTWARE\Wow6432Node\AUTOLABDEVICESERVICE\bondtest", True).GetValue("baudrate"))
            If Registry.LocalMachine.OpenSubKey("SOFTWARE\Wow6432Node\AUTOLABDEVICESERVICE\bondtest", True).GetValue("parity") = 0 Then
                .Parity = Parity.None
           End If
            If Registry.LocalMachine.OpenSubKey("SOFTWARE\Wow6432Node\AUTOLABDEVICESERVICE\bondtest", True).GetValue("stopbits") = 1 Then
                .StopBits = StopBits.One
            End If
            .DataBits = CInt(Registry.LocalMachine.OpenSubKey("SOFTWARE\Wow6432Node\AUTOLABDEVICESERVICE\bondtest", True).GetValue("bytesize"))
            .Handshake = Handshake.None
            If Registry.LocalMachine.OpenSubKey("SOFTWARE\Wow6432Node\AUTOLABDEVICESERVICE\bondtest", True).GetValue("RtsControl") = 1 Then
                .RtsEnable = True
            Else
                .RtsEnable = False
           End If
        End With
        serialPort.Open()

        'debug
        'ErrorLog2("Listening to COM 19, SerialPort has been Opened")

    Catch ex As Exception
         ErrorLog2(Now.ToString & ex.tostring)
    End Try
End Sub

Public Function Filelocator() As String

    ' Dim filePath As String = IO.Path.Combine(Application.StartupPath, "bondtest.bat")
    Dim filePath As String = IO.Path.Combine("C:\Program Files (x86)\PIPC\Interfaces\Lab", "BondTest.bat")
    'Dim reader As New System.IO.StreamReader(filePath)
    Dim LineNumber = 4
    Using file As New StreamReader(filePath)
        ' Skip all preceding lines: '
        For i As Integer = 1 To LineNumber - 1
            If file.ReadLine() Is Nothing Then
                ErrorLog2("LineNumber")
            End If
        Next
        ' Attempt to read the line you're interested in: '
        Dim line As String = file.ReadLine()
        If line Is Nothing Then
            ErrorLog2("LineNumber")
        End If
        Return line
    End Using
End Function

Private Sub serialPort_DataReceived(ByVal sender As Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort.DataReceived
    Try
        If GetBondInterfaceStatus = 1 Then
            UPdateVariable()
        Else
            exit Sub
        End If
    Catch ex As Exception
        Errorlog2(Ex.Tostring)
    End Try
End Sub



#End Region

#Region "String Handling"
Public Sub UPdateVariable()
    With RawString
        .Append(serialPort.ReadLine())
    End With
    try
        ErrorLog2(now.ToString & RawString.ToString)
        InsertTestDataDEBUG(GetRecordID, BondTest, BondTestType.ToUpper.ToString, GetBondPosition(), StringParser(RawString.ToString()), RawString.tostring)
        InsertTestData(GetRecordID, BondTest, BondTestType.ToUpper.ToString, GetBondPosition(), StringParser(RawString.ToString()))
        RawString.Clear()
    Catch ex As Exception
        ErrorLog2(ex.ToString())
    End Try
End Sub

Public Function StringParser(RawString As String)As Double ()
    Dim Moisture = RawString
    Dim pattern As String = "[0-9],"
    Dim regex As New Regex(pattern)
    Dim Counter As Integer = 0
    Dim dblValues(1) As Double
    Dim values As String() = Moisture.Split(New Char() {" "c})


    for i = 0 to values.Count - 1
        if regex.IsMatch(values(i)) Then
            dblValues(Counter) = CDbl(values(i).Substring(0,1))
            Counter = Counter + 1
        Elseif values(i) = "" Then
            continue for
        else
            if Double.TryParse(values(i), dblValues(Counter)) Then
                Counter = Counter + 1 
            End If
        End If

    Next
    Return dblValues
End Function

#End Region

#Region "SQL Statements"
Private Sub InsertTestData(RecordID As Integer, BondTest As Integer, TestType As String, TestPos As Integer, dataArray() As Double)
    Dim InsertQuery As String = ""
    Dim conn As New BondSQLConnection("PaperTests")
   ' Dim TestPos = StartingTestPos + (CInt(dataArray(0)) - 1)

    conn("@RecordID") = RecordID
    conn("@Test") = BondTest
    conn("@TestType") = TestType
    conn("@TestPos") = TestPos
    conn("@TestData") = dataArray(1)
    conn("@TestDateTime") = now.tostring

    InsertQuery = "INSERT INTO PaperTests.dbo.PaperTestValues(ReelRecordID, Test, TestLocation, TestPosition, TestValue, TestTimeStamp) VALUES (@RecordID, @Test, @TestType, @TestPos, @TestData, @TestDateTime)"
    Try
        conn.ExecuteNonQuery(InsertQuery)
        IncrementTestPosition
    Catch ex As Exception
        ErrorLog2(ex.ToString())
    End Try

End Sub

Private Sub InsertTestDataDEBUG(RecordID As Integer, BondTest As Integer, TestType As String, TestPos As Integer, dataArray() As Double, rawString As String)
    Dim InsertQuery As String = ""
    Dim conn As New BondSQLConnection("PaperTests")

    conn("@RecordID") = RecordID
    conn("@Test") = BondTest
    conn("@TestType") = TestType
    conn("@TestPos") = TestPos
    conn("@TestData") = dataArray(1)
    conn("@RawString") = rawString
    conn("@TestDateTime") = now.tostring

    InsertQuery = "INSERT INTO PaperTests.dbo.InterfaceTesting(ReelRecordID, Test, TestLocation, TestPosition, TestValue, TestTimeStamp, RawValue) VALUES (@RecordID, @Test, @TestType, @TestPos, @TestData, @TestDateTime, @RawString)"
    Try
        conn.ExecuteNonQuery(InsertQuery)
    Catch ex As Exception
        ErrorLog2(ex.ToString())
    End Try

End Sub

Private Sub IncrementTestPosition()
    Dim tempPosition As Integer = GetBondPosition()
    Dim FrontOriginalMax = 5
    Dim CenterOriginalMax = 15
    Dim BackOriginalMax = 25
    Dim FrontRetestOrWinderMax = 10
    Dim CenterRetestOrWinderMax = 20
    Dim BackRetestOrWinderMax = 30

    If tempPosition = FrontOriginalMax Then
        tempPosition = 11
    else if tempPosition = CenterOriginalMax Then
        tempPosition = 21
    else if tempPosition = BackOriginalMax Then
        tempPosition = 1
    Else If tempPosition = FrontRetestOrWinderMax then
        tempPosition = 1
    Else If tempPosition = CenterRetestOrWinderMax then
        tempPosition = 1
    Else If tempPosition = BackRetestOrWinderMax then
        tempPosition = 1
    else 
        tempPosition = tempPosition + 1
    End If
    SetBondPosition(tempPosition.tostring)
End Sub

#End Region

#Region "Get PiValues"
Private Function GetRecordID() As Int64
    Dim RecordID As Int32 = 0
    Try
        Dim piserver As New PIServer("valpi", "piadmin", "fatb0y",True)
        RecordID = piserver.GetCurrentValue("PAPERLAB:PaperLabReelSelected")
    Catch ex As Exception
        ErrorLog2(ex.ToString())
    End Try
    Return RecordID
End Function

Private Function GetBondPosition() As Int64
    Dim BondPos As Int32 = 0
    Try
        Dim piserver As New PIServer("valpi", "piadmin", "fatb0y",True)
        BondPos = CInt(piserver.GetCurrentValue("PAPERLAB:SBOND.POS"))
    Catch ex As Exception
        ErrorLog2(ex.ToString())
    End Try
    Return BondPos
End Function
Private Sub SetBondPosition(pos As String) 
    Try
        Dim piserver As New PIServer("valpi", "piadmin", "fatb0y",True)
       piserver.WriteValue("PAPERLAB:SBOND.POS", pos)
    Catch ex As Exception
        ErrorLog2(ex.ToString())
    End Try
End Sub

Private Function BondTestType() As String
    Dim TestType As String = ""
    Try
        Dim piserver As New PIServer("valpi", "piadmin", "fatb0y",True)
        TestType = piserver.GetCurrentValue("M1:BOND.TYPE")
    Catch ex As Exception
        ErrorLog2(ex.ToString())
    End Try
    Return TestType
End Function

Private Function BondReelLoc() As String
    Dim ReelLoc As String = ""
    Try
        Dim piserver As New PIServer("valpi", "piadmin", "fatb0y",True)
        ReelLoc = piserver.GetCurrentValue("M1:BOND.ReelLoc")
    Catch ex As Exception
        ErrorLog2(ex.ToString())
    End Try
    Return ReelLoc
End Function

Private Function GetBondInterfaceStatus() As Integer
    Dim Status As Integer = 0
    Try
        Dim piserver As New PIServer("valpi", "piadmin", "fatb0y",True)
        Status = CInt(piserver.GetCurrentValue("PAPERLAB:BOND_INTERFACE.S"))
    Catch ex As Exception
        ErrorLog2(ex.ToString())
    End Try
    Return Status
End Function

#End Region

#Region "Debug"

    Private Sub ErrorLog(RecordID As Int32, BondTest As Integer, ReelLoc As String, TestType As String, StartingTestPos As Integer, dataArray() As Double)
    Dim SavePath As String = "C:\Program Files (x86)\PIPC\Interfaces\Lab"
    Dim NameOfFile As String = "BondTest Debug File"
    Dim TestPos = StartingTestPos + (CInt(dataArray(0)) - 1)

    If System.IO.File.Exists(SavePath & "\" & NameOfFile & ".txt") Then
        Using sw As StreamWriter =  New StreamWriter(SavePath & "\" & NameOfFile & ".txt", True)

          '  For i = 0 To dataArray.Count -1 
                sw.WriteLine(" ")
                sw.WriteLine(RecordID & "   " & BondTest & "    " & ReelLoc & "    " & TestType  & "   " & TestPos & "   " & dataArray(1).ToString)
              '  TestPos = TestPos + 1
          '  Next
        End Using
    else
        File.Create(SavePath & "\" & NameOfFile & ".txt").Dispose()
        Using sw As StreamWriter = File.CreateText(SavePath & "\" & NameOfFile & ".txt")
            'For i = 0 To dataArray.Count -1 
                sw.WriteLine(" ")
                sw.WriteLine(RecordID & "   " & BondTest & "    " & ReelLoc & "    " & TestType  & "   " & TestPos & "   " & dataArray(1).ToString)
              '  TestPos = TestPos + 1
            'Next
        End Using
    End If
End Sub

Private Sub ErrorLog2(dataArray as string)
    Dim SavePath As String = "C:\Program Files (x86)\PIPC\Interfaces\Lab"
    Dim NameOfFile As String = "BondTest Debug File"
   ' Dim TestPos = StartingTestPos

    If System.IO.File.Exists(SavePath & "\" & NameOfFile & ".txt") Then
        Using sw As StreamWriter = New StreamWriter(SavePath & "\" & NameOfFile & ".txt", True)
                sw.WriteLine(" ")
                sw.WriteLine(dataArray)
        End Using
    else
        File.Create(SavePath & "\" & NameOfFile & ".txt").Dispose()
        Using sw As StreamWriter = File.CreateText(SavePath & "\" & NameOfFile & ".txt")
                sw.WriteLine(" ")
                sw.WriteLine(dataArray)
        End Using
    End If
End Sub

#End Region

Это скриншот ошибок:

errors

Заранее спасибо

Ответы [ 2 ]

0 голосов
/ 18 октября 2018

Обновление: так как Тимми говорил, что соединение удаляется сборщиком мусора.поэтому я объявил объект как общую переменную в классе

Shared Dim WithEvents serialPort as IO.Ports.SerialPort

, а в методе OnStart я инициировал его как новый последовательный порт и включил его.не выдает никаких ошибок, так как сборка мусора не избавится от него.Надеюсь, что это поможет кому-то с подобной проблемой.

0 голосов
/ 20 сентября 2018

Обычно после открытия последовательного порта в .NET он остается открытым в течение произвольного времени.Я написал несколько приложений .NET, где последовательные порты использовались месяцами или годами без перезапуска приложения или компьютера, и они хорошо работают.

Согласно опубликованной вами информации об исключении, похоже, что этот последовательный порт был удален.Есть несколько возможных причин.

  1. Использование плохого драйвера или HW, который отключает ваш последовательный порт.Я использовал много конвертеров USB-RS232, и у некоторых из них были плохие драйверы, поэтому иногда порты были случайно отключены и выброшено ObjectDisposedException.В более ранних выпусках Windows (XP) ОС даже «сине-экранирована». Здесь - дополнительная информация о такой ситуации, когда выбрасывается ObjectDisposedException.

Это известная проблема с SerialPort.Удаление устройства вызывает неуловимое исключение в фоновом потоке, которое оно использует (WaitForCommEvent).Единственные решения - не использовать SerialPort или создавать файл .config, который переводит режим обработки необработанных исключений в поведение .NET 1.1.

Кабель USB вашего преобразователя RS232 отключен вручную.Если вы делаете это, большинство драйверов обычно отключают все дескрипторы вашего последовательного порта, и .NET выдает ObjectDisposedException.

Также проверьте настройки управления питанием на USB-порту, если USB-to-Используется преобразователь RS232. Power Management Попробуйте снять этот флажок на USB-устройстве, к которому подключен преобразователь.

Ошибка SW в вашем коде.

Всегда желательно (особенно если используется конвертер) попробовать больше типов конвертеров, просто чтобы убедиться, что в устройстве / драйвере HW нет проблем.

...