这是一个UI线程问题吗?有没有一种简单的方法来解决它?

时间:2012-01-23 18:01:48

标签: vb.net

我正在与USB-HID设备通信。它将成功完成数百个发送 - 接收请求,但偶尔会出现Null异常错误。

这是一个线程问题吗?

FormMain.vb:

myHidDevice.transmitPacket(Packet)
myHidDevice.resetEvent.WaitOne(6)
If myHidDevice.rxDataReady = True then
    ' Life is good

MyHidDevicePort.vb

Public Sub DataReceivedHandler(ByVal sender as Object, dataReceived as DataReceivedEventArgs)
    if dataReceived.data Is Nothing Then
        Exit Sub
    Else
        Dim rDataPacket As List(Of Byte) = dataReceived.data.ToList()
        For Each element in rDataPacket
            rxData.dataPacket(i) = element
        rxDataReady = True
        resetEvent.Set()

MySensorClass.vb

Public Overrides Function processPacket(ByRef rxStruct as rStruct, ByVal txPacket()) as Boolean
....
Select Case rxStruct.dataPacket(4)
    Case MOD_DISPLAY_SET_BRIGHTNESS
        rxData(0) = rxStruct.dataPacket(5)
    ...

在rxData.dataPacket(i)=元素我会偶尔得到一个NullReference错误。我可以将它包含在try / catch语句中,但是如果可能的话我想修复根问题。

这个设备正在与微控制器进行通信,它们可能并不总能给出价值......但我的感觉是这是某种UI线程问题。在调试时,即使存在空异常,很多时候似乎确实存在dataReceived.data.ToList()中的数据。有没有一种简单的方法可以将整个数据处理例程放在与UI分离的线程上?

修改:更改了代码以匹配答案,并提供有关其使用位置的详细信息。在向HID设备发出大约1,000个完成的发送/接收请求后仍然获得NullReferenceExceptions。

2 个答案:

答案 0 :(得分:1)

评论中的对话框太严格了,所以我会尝试这个作为答案。不幸的是,仍然没有足够的代码来提供完整的答案。

一些未知样本:

什么是rxData(客户类,SDK的一部分,结构)?

代码示例i中的rxData.dataPacket(i) = element来自哪里,我看不到它已经死亡或递增。

为什么表单在myHidDevice.resetEvent.WaitOne(6)上等待,一旦认为有成功,它会怎么做?

processPacket如何/何时被召唤?

我一般可以推荐的是,对共享状态的访问包含在SyncLock中。在您的情况下,这包括rxData和rxDataReady。

在线程事件回调中,您需要:

SyncLock(syncRoot)
   For Each element in rDataPacket             
      rxData.dataPacket(i) = element
   next         
   rxDataReady = True         
   resetEvent.Set() 
End SyncLock

在您正在等待回复的主表单中,您还需要包含对ready标志的访问权限:

SyncLock(myHidDevice.syncRoot)
   If myHidDevice.rxDataReady = True then  

      ' do something that consumes the data read in the thread

   End If
End SyncLock

你必须注意你在读和写中持有锁的时间,因为你不能同时做两件事。

总而言之,如果您的代码被重构一点以使线程问题更容易处理,我不会感到惊讶。您建议的阻塞队列/收集可能是个好主意。仅仅知道你的设计/代码还没有给出更具体的建议。

答案 1 :(得分:0)

如果你知道你的对象可能是 null ,那么将它置于try-catch块中将是处理这种情况的不正确的方式,因为它将被视为按例外编码。而是在设置对象之前对其进行空检查。 e.g。

If Not dataReceived.data Is Nothing Then
   Dim rDataPacket As List(Of Byte) = dataReceived.data.ToList() 
End If

如果你的问题与单个数组元素为空,那么在设置/访问它们之前,你还应检查它们以确保它们存在。