我已经编写了一个服务应用程序,该应用程序侦听端口可能通过的任何通信,我们的实验室将运行某种测试,该测试每隔几个小时发送一次串行数据。运行该服务可以很好地收集数据几个小时,然后神秘地停止。系统事件日志显示服务意外终止。并且在应用程序事件日志中,它具有更具描述性的.NET错误,
应用程序:BondTestService.exe框架版本:v4.0.30319 说明:由于未处理的异常,进程已终止。 异常信息:System.ObjectDisposedException在 System.Runtime.InteropServices.SafeHandle.DangerousAddRef(布尔 ByRef) System.StubHelpers.StubHelpers.SafeHandleAddRef(System.Runtime.InteropServices.SafeHandle, 布尔ByRef),位于 Microsoft.Win32.UnsafeNativeMethods.GetOverlappedResult(Microsoft.Win32.SafeHandles.SafeFileHandle, System.Threading.NativeOverlapped *,Int32 ByRef,布尔值) System.IO.Ports.SerialStream + EventLoopRunner.WaitForCommEvent()在 System.Threading.ThreadHelper.ThreadStart_Context(System.Object)在 System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, System.Threading.ContextCallback,System.Object,Boolean)在 System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback,System.Object,Boolean)在 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
这是错误的屏幕截图:
谢谢
答案 0 :(得分:1)
通常,在.NET中打开串行端口后,它将保持打开状态任意时间。我已经写了几个.NET应用程序,其中串行端口使用了数月或数年,而没有重新启动应用程序或计算机,并且它们运行良好。
根据您发布的异常信息,它看起来好像已经处理了串行端口。有几种可能的原因。
ObjectDisposedException
。在早期的Windows版本(XP)中,操作系统甚至“蓝屏”。 Here是有关抛出ObjectDisposedException
的情况的更多信息。这是SerialPort的已知问题。设备删除会在它使用的后台线程(WaitForCommEvent)中导致无法捕获的异常。唯一的解决方案是不使用SerialPort或创建一个.config文件,该文件将未处理的异常捕获模式放回.NET 1.1行为。
RS232转换器的USB电缆已手动断开。如果这样做,大多数驱动程序通常会断开与串口的所有句柄,.NET会抛出ObjectDisposedException
。
如果使用了USB转RS232转换器,还请检查USB端口上的电源管理设置。尝试在连接了转换器的USB设备上取消选中此选项。
< / li>代码中的SW错误。
始终建议(尤其是如果使用转换器的话)尝试更多类型的转换器,以确保硬件设备/驱动程序没有问题。
答案 1 :(得分:0)
更新:就像蒂米(Timmy)所说的那样,该连接正被垃圾回收处理。所以我在类中将对象声明为共享变量
Shared Dim WithEvents serialPort as IO.Ports.SerialPort
,然后在OnStart方法中将其启动为新的串行端口并继续使用。不会抛出任何错误,因为垃圾回收不会处理它。希望这可以帮助遇到类似问题的人。