StackTrace:在System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32 errorCode,UInt32 numBytes,NativeOverlapped * pOVERLAP) 资料来源:mscorlib
我在目标源中看到一些关于反射的东西。所以我会发布使用反射的极少量代码。
我通常能够轻松找到NullReferenceExceptions。这个虽然似乎不是我的代码,但我无法弄清楚是为了挽救我的生命。我在VB.net中有这个代码机器人,而C#.Net都有同样的问题。我认为我的问题在于我的指针是如何工作的,但我可能是错的。
代码很简单。我有一个条形码扫描仪通过usb连接,处于COM模式。我从另一个使用相同条形码的程序中复制了我的一些代码,这些代码完美无缺。但总结一下它的作用是打开,然后,通过使用反射,获取指向开放com端口的指针,设置一个DataEventListener。当我扫描我等待100ms的东西时,然后以字符串形式吐出数据。很简单。我的代码和另一个有问题的代码之间的区别在于我必须得到指针。要打开我的扫描仪,我需要使用IntPtr指向comport。 C#我使用IntPtr,在VB中我使用SafeFileHandle。两者都有相同的错误。发生错误的唯一时间是触发数据事件。这就是为什么我认为它必须与句柄。奇怪的是需要把手打开和关闭成像器,所以我知道我有一个有效的手柄。 (只是不知道它是否被保留)所以有没有人有任何帮助或资源,为什么我有这个错误?
首先...... VB.NET 公共类ImagerOposDevice 继承AbstractOPOSDevice 昏暗的PortHandle作为SafeFileHandle 昏暗的ImagerPort作为SerialPort 公共exitCode = 1 Sub New(ByVal comName As String) ImagerPort =新的SerialPort(comName) 结束子
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);
答案 0 :(得分:0)
事实证明,LightStriker让我看到了昨天让我眼花缭乱的迷雾。我仍然没有vb.net版本工作,但它最终是因为我的C#程序中使用的IntPtr没有被保留,当一个单独的线程(IE的数据事件)调用它。当我逐步完成数据事件部分时,直到我调用TurnImagerOff()部分才会失败。这是一个简单的解决方案,我所要做的就是将我的串口和我的IntPtr改为静态成员。我在VB.net代码中尝试过这个...但显然我不够聪明,无法解决这个问题。哦,今天是另一天,至少有50%的代码可以使用。
所以对于那些有空引用错误但无法在任何地方找到它的人。并且Stack Trace不会给你一个行号,检查正在调用任何指针成员的另一个线程上运行的任何内容。 (或反映为指针)。检查数据事件,线程池,后台工作人员,计时器,代表等。我希望我的愚蠢行为会帮助其他人。