StackTrace:在 System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* pOVERLAP) 来源:mscorlib
我在目标源中看到了一些关于反射的东西。所以我会发布非常少量的使用反射的代码。
我通常能够轻松找到 NullReferenceExceptions。虽然这似乎不是我的代码,但我无法弄清楚以挽救我的生命。我在 VB.net 中有这个代码机器人,和 C#.Net 都有同样的问题。我认为我的问题在于我的指针是如何工作的,但我可能是错的。
代码很简单。我有一个通过 USB 连接的条形码扫描仪,它处于 COM 模式。我从另一个程序中复制了一些代码,该程序使用了同样可以完美运行的条形码。但是总结一下它的作用是打开,然后通过反射,获取指向打开的com端口的指针,设置一个DataEventListener。当我扫描某些东西时,我会等待 100 毫秒,然后以字符串形式吐出数据。尽可能简单。我的代码与另一个完美运行的代码之间的区别在于我必须获得指针。要打开我的扫描仪,我需要一个指向使用 IntPtr 的 comport 的指针。C# 我使用 IntPtr,在 VB 中我使用 SafeFileHandle。两者都有相同的错误。唯一发生错误的时间是触发数据事件时。这就是为什么我认为它必须与手柄有关。奇怪的是需要手柄来打开和关闭成像仪,所以我知道我有一个有效的手柄。(只是不知道它是否被保留)那么有人对我为什么会出现这个错误有任何帮助或资源吗?
首先.. VB.NET Public Class ImagerOposDevice Inherits AbstractOPOSDevice Dim PortHandle As SafeFileHandle Dim ImagerPort As SerialPort Public exitCode = 1 Sub New(ByVal comName As String) ImagerPort = New SerialPort(comName) End Sub
Protected Overrides Function Open() As Boolean
ImagerPort.Open()
PortHandle = GetHandleFromSerialPort(ImagerPort)
If Not PortHandle.IsInvalid Then
AddHandler ImagerPort.DataReceived, AddressOf DataReceivedHandler
End If
Return (Not PortHandle.IsInvalid)
End Function
Protected Overrides Sub Close()
Try
ImagerPort.Close()
ImagerPort.Dispose()
Catch ex As Exception
Console.WriteLine(ex.Message)
Console.ReadLine()
End Try
End Sub
Protected Overrides Function RunCommand(ByVal X As Integer) As Boolean
If X = 0 Then
Return TurnImagerOn()
ElseIf X = 1 Then
Return TurnImagerOff()
Else
Return False
End If
End Function
Private Shared Function GetHandleFromSerialPort(ByVal sp As SerialPort) As SafeFileHandle
Dim BaseStream As Object = sp.BaseStream
Dim BaseStreamType As Type = BaseStream.GetType
Return BaseStreamType.GetField("_handle", BindingFlags.NonPublic Or BindingFlags.Instance).GetValue(BaseStream)
End Function
Private Sub DataReceivedHandler(ByVal sender As Object, ByVal e As SerialDataReceivedEventArgs)
Try
'Dim sp As SerialPort = CType(sender, SerialPort)
System.Threading.Thread.Sleep(100)
Dim len = ImagerPort.BytesToRead
Dim buffer(len - 1) As Byte
ImagerPort.Read(buffer, 0, len)
Dim indata As String = System.Text.ASCIIEncoding.ASCII.GetString(buffer)
Console.WriteLine("Data Received:")
Console.Write(indata)
TurnImagerOff()
Catch ex As Exception
Console.WriteLine(ex.Message)
End Try
exitCode = 0
End Sub
在我的主要形式中,它是直截了当的
imager = New ImagerOposDevice("COM7")
imager.OpenDevice()
imager.SendCommand(0)
For index = 1 To 100 Step 1
System.Threading.Thread.Sleep(100)
If imager.exitCode = 0 Then
Exit For
End If
Next
Console.WriteLine("Press Enter to Close")
Console.ReadLine()
CloseDevices()
现在是 C# 代码。它是一种窗口形式,但概念几乎相同。
private SerialPort devicePort;
private IntPtr deviceHandle;
public Imager(string Port) : base()
{
devicePort = new SerialPort(Port);
}
protected override bool Open()
{
try
{
devicePort.Open();
deviceHandle = GetHandleFromSerialPort(devicePort);
Console.WriteLine("Device Handle:{0}", deviceHandle);
Console.WriteLine("Device Open:{0}", devicePort.IsOpen);
}
catch(Exception ex)
{
Console.WriteLine(ex.Message);
}
return devicePort.IsOpen;
}
protected override bool Close()
{
devicePort.Close();
devicePort.Dispose();
return true;
}
protected override CommandReturnCodes RunCommand(int command)
{
switch (command)
{
case 0:
TurnImagerOn();
break;
case 1:
TurnImagerOff();
break;
case 2:
ReadLatch();
break;
case 3:
GetPartNumber();
break;
case 4:
GetSerialNumber();
break;
case 5:
GetProductString();
break;
default:
return CommandReturnCodes.FAIL;
}
return CommandReturnCodes.SUCCESS;
}
private static IntPtr GetHandleFromSerialPort(SerialPort sp)
{
Type t = typeof(SerialPort);
BindingFlags bf = BindingFlags.Instance | BindingFlags.NonPublic;
FieldInfo fi = t.GetField("internalSerialStream", bf);
object ss = fi.GetValue(sp);
Type t2 = fi.FieldType;
FieldInfo fi2 = t2.GetField("_handle", bf);
SafeFileHandle _handle = (SafeFileHandle)fi2.GetValue(ss);
Type t3 = typeof(SafeFileHandle);
FieldInfo fi3 = t3.GetField("handle", bf);
IntPtr handle = (IntPtr)fi3.GetValue(_handle);
return handle;
}
public void TurnOnImagerEventListener()
{
devicePort.DataReceived += new SerialDataReceivedEventHandler(devicePort_DataReceived);
}
void devicePort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
System.Threading.Thread.Sleep(100);
SerialPort imager = sender as SerialPort;
byte[] buffer = new byte[imager.BytesToRead];
imager.Read(buffer, 0, imager.BytesToRead);
var scannedText = System.Text.Encoding.ASCII.GetString(buffer).Trim();
SendBarcodeEvent(scannedText);
TurnImagerOff();
Console.WriteLine(scannedText);
}
并称它为同一件事
im = new Imager(comportBox.Text);
im.OpenDevice();
im.TurnOnImagerEventListener();
im.BarcodeScanned += new DataAvailableHandler(DeviceInformationReceived);