StackTrace: System.Threading._IOCompletionCallback.PerformIOCompletionCallback (UInt32 errorCode、UInt32 numBytes、NativeOverlapped* pOVERLAP) ソース: mscorlib
ターゲット ソースにリフレクションに関する何かが表示されます。そこで、リフレクションを使用する非常に少量のコードを投稿します。
通常、NullReferenceExceptions は簡単に見つけることができます。これは私のコードではないようですが、命を救うためにそれを理解することはできません。私はこのコード ボットを VB.net と C#.Net に持っています。どちらも同じ問題を抱えています。私の問題はポインターの動作にあると思いますが、間違っている可能性があります。
コードは簡単です。COM モードの USB 経由で接続されたバーコード スキャナがあります。完全に機能するこの同じバーコードを使用する別のプログラムからコードの一部をコピーしました。しかし、それが何をするかを要約すると、それが開き、リフレクションを使用して、開いている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);