首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >VB.Net等待抛出一个NullReferenceException

VB.Net等待抛出一个NullReferenceException
EN

Stack Overflow用户
提问于 2021-03-29 06:25:38
回答 1查看 61关注 0票数 0

下面的代码不时引发NullReferenceException错误。这种情况并不总是会发生,但假设在10次尝试中至少有2-3次,我得到了这个恼人的"System.NullReferenceException“屏幕。

我正在从数据采集卡读取数据,DATAQ 4208 U。在读取“停止”命令时,会发生此错误。另一个问题是我不是编码和VB.Net方面的专家。

它抛出错误的点在末尾(当然,我刚才引用了代码,但没有结束)

等待TargetDevice.ReadDataAsync(cancelRead.Token)

代码语言:javascript
复制
 Private Async Sub btnState_Click(sender As Object, e As EventArgs) Handles btnState.Click
    If cancelRead IsNot Nothing Then

        'Get here if an acquisition process is in progress and we've been commanded to stop
        cancelRead.Cancel() 'cancel the read process
        cancelRead = Nothing
        Await taskRead 'wait for the read process to complete
        taskRead = Nothing
        Await TargetDevice.AcquisitionStopAsync() 'stop the device from acquiring 

    Else
        'get here if we're starting a new acquisition process
        TargetDevice.Channels.Clear() 'initialize the device
        ConfigureAnalogChannels()
        ConfigureDigitalChannels()

        If SampleRateBad() Then
            'get here if requested sample rate is out of range
            'It's a bust, so...
            btnState.Enabled = True
            Exit Sub
        End If
        'otherwise, the selected sample rate is good, so use it. The class automatically adjusts
        'decimation factor and the protocol's sample rate denominator to yield a sample rate value as close as possible to
        'the value asked for in tbSampleRate.Text. The class also automatically maximizes decimation factor as a function of 
        'channels' AcquisitionMode settings. For this reason Acquisition mode should be defined for all enabled channels
        'before defining sample rate. 
        TargetDevice.SetSampleRateOnChannels(tbSampleRate.Text)

        Try
            Await TargetDevice.InitializeAsync() 'configure the device as defined. Errors if no channels are enabled
        Catch ex As Exception
            'Detect if no channels are enabled, and bail if so. 
            MessageBox.Show("No enabled analog or digital channels.",
                            "Configuration Problem", MessageBoxButtons.OK, MessageBoxIcon.Error)
            btnState.Enabled = True
            Exit Sub
        End Try

        'now determine what sample rate per channel the device is using from the 
        'first enabled input channel, and display it
        Dim FirstInChannel As Dataq.Devices.DI4208.ChannelIn
        Dim NoInputChannels As Boolean = True
        For index = 0 To TargetDevice.Channels.Count - 1
            If TypeOf TargetDevice.Channels(index) Is Dataq.Devices.IChannelIn Then
                FirstInChannel = TargetDevice.Channels(index)
                lblDecimation.Text = FirstInChannel.AcquisitionMode.Samples
                NoInputChannels = False
                Exit For
            End If
        Next
        If NoInputChannels Then
            MessageBox.Show("Please configure at least one analog channel or digital port as an input",
                            "No Inputs Enabled", MessageBoxButtons.OK, MessageBoxIcon.Error)
            btnState.Enabled = True
            Exit Sub
        End If
        'Everything is good, so...
        btnState.Text = "Stop" 'change button text to "Stop" from "Start"
        cancelRead = New CancellationTokenSource() ' Create the cancellation token
        Await TargetDevice.AcquisitionStartAsync() 'start acquiring

        ' NOTE: assumes at least one input channel enabled
        ' Start a task in the background to read data
        taskRead = Task.Run(Async Function()
                                'capture the first channel programmed as an input (MasterChannel)
                                'and use it to track data availability for all input channels
                                Dim MasterChannel As Dataq.Devices.IChannelIn = Nothing
                                For index = 0 To TargetDevice.Channels.Count
                                    If TypeOf TargetDevice.Channels(index) Is Dataq.Devices.IChannelIn Then
                                        MasterChannel = TargetDevice.Channels(index) ' we have our channel 
                                        Exit For
                                    End If
                                Next

                                ' Keep reading while acquiring data
                                While TargetDevice.IsAcquiring
                                    ' Read data and catch if cancelled (to exit loop and continue)
                                    Try
                                        'throws an error if acquisition has been cancelled
                                        'otherwise refreshes the buffer DataIn with new data
                                        'ReadDataAsync moves data from a small, temp buffer between USB hadrware and Windows
                                        'into the SDK's DataIn buffer. ReadDataAsync should be called frequently to prevent a buffer
                                        'overflow at the hardware level. However, buffer DataIn can grow to the size of available RAM if necessary.
                                        Await TargetDevice.ReadDataAsync(cancelRead.Token)
                                    Catch ex As OperationCanceledException
                                        'get here if acquisition cancelled
                                        Exit While
                                    End Try
EN

回答 1

Stack Overflow用户

发布于 2021-03-29 13:47:16

您的问题在于这个顺序:

代码语言:javascript
复制
    cancelRead.Cancel() 'cancel the read process
    cancelRead = Nothing
    Await taskRead 'wait for the read process to complete

如果此时调用cancelRead.Cancel(),任务目前正处于Await TargetDevice.ReadDataAsync步骤上,则此操作将有效。

当问题不在这一步的时候,问题就会发生。调用Cancel on cancelRead并不会产生任何神奇的效果,特别是它不会自发地在任务中发出OperationCanceledException。它将令牌置于已取消的状态,因此OperationCanceledException将在下次访问它时发出.但是,该任务尝试执行Await TargetDevice.ReadDataAsync的下一次迭代,并弹出一个NullRefException,因为您试图从空cancelRead中获取Token

如果您将cancelRead的设置与Await taskRead交换为nothing,以等待进程完成,则应解决此问题。

另一个注意事项:Task实现了IDisposable,因此在将其设置为Nothing之前,您应该在taskRead上调用Dispose,否则可能会有泄漏资源的风险。同样,对于cancelReadCancellationTokenSource也实现了IDisposable

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/66849555

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档