为什么在成功操作后会发生此 NRE

本文关键字:NRE 成功 操作 为什么 | 更新日期: 2023-09-27 18:35:17

我的 Windows CE 应用程序中有一个项目范围的异常处理程序,当我的应用程序在特定情况下崩溃时,它会记录以下内容:

Message: From application-wide exception handler: System.NullReferenceException: NullReferenceException
   at HHS.FrmDelivery.ReaderForm_Activated(Object sender, EventArgs e)
   at System.Windows.Forms.Form.OnActivated(EventArgs e)
   at System.Windows.Forms.Form.WnProc(WM wm, Int32 wParam, Int32 lParam)
   at System.Windows.Forms.Control._InternalWnProc(WM wm, Int32 wParam, Int32 lParam)
   at Microsoft.AGL.Forms.DLG.MessageBox(String wszCaption, String wszBody, MessageBoxButtons mbtyp, MessageBoxIcon mbicon, MessageBoxDefaultButton defbtn, DialogResult& mbret)
   at System.Windows.Forms.MessageBox.Show(String text, String caption, MessageBoxButtons buttons, MessageBoxIcon icon, MessageBoxDefaultButton defaultButton)
   at HHS.FrmDelivery.buttonSave_Click(Object sender, EventArgs args)

所以问题似乎出在 FrmDelivery.ReaderForm_Activated() 中,这是处理条形码扫描的表单代码的一部分:

private void ReaderForm_Activated(object sender, EventArgs e)
{
    ExceptionLoggingService.Instance.WriteLog("Reached frmDelivery.ReaderForm_Activated");
    // If there are no reads pending on barcodeReader start a new read
    if (!this.barcodeReaderData.IsPending)
    {
        this.StartRead();
    }
}

在上下文中,以下是该表单上与条形码扫描相关的整个代码:

public partial class FrmDelivery : Form
{
    . . .
    // Barcode stuff
    private Symbol.Barcode.Reader barcodeReader;
    private Symbol.Barcode.ReaderData barcodeReaderData;
    private EventHandler barcodeEventHandler;
    // </ Barcode stuff
// form's overloaded constructor
public FrmDelivery(NewDelivery newDel)
{
    InitializeComponent();
    . . .
    textBoxUPC_PLU.Focus();
}
// Barcode scanning code
private void textBoxUPC_PLU_GotFocus(object sender, EventArgs e)
{
    ExceptionLoggingService.Instance.WriteLog("Reached frmDelivery.textBoxUPC_PLU_GotFocus");
    if (this.InitReader())
    {
        this.StartRead();
    }
}
private bool InitReader()
{
    ExceptionLoggingService.Instance.WriteLog("Reached frmDelivery.InitReader");
    // If reader is already present then retreat
    if (this.barcodeReader != null)
    {
        return false;
    }
    // Create new reader, first available reader will be used.
    this.barcodeReader = new Symbol.Barcode.Reader();
    // Create reader data
    this.barcodeReaderData = new Symbol.Barcode.ReaderData(
        Symbol.Barcode.ReaderDataTypes.Text,
        Symbol.Barcode.ReaderDataLengths.MaximumLabel);
    // Create event handler delegate
    this.barcodeEventHandler = this.BarcodeReader_ReadNotify;
    // Enable reader, with wait cursor
    this.barcodeReader.Actions.Enable();
    this.barcodeReader.Parameters.Feedback.Success.BeepTime = 0;
    this.barcodeReader.Parameters.Feedback.Success.WaveFile = "''windows''alarm3.wav";
    // Attach to activate and deactivate events
    this.Activated += ReaderForm_Activated;
    this.Deactivate += ReaderForm_Deactivate;
    return true;
}
private void StartRead()
{
    ExceptionLoggingService.Instance.WriteLog("Reached frmDelivery.StartRead");
    // If we have both a reader and a reader data
    if ((this.barcodeReader != null) && (this.barcodeReaderData != null))
    {
        // Submit a read
        this.barcodeReader.ReadNotify += this.barcodeEventHandler;
        this.barcodeReader.Actions.Read(this.barcodeReaderData);
    }
}
private void BarcodeReader_ReadNotify(object sender, EventArgs e)
{
    ExceptionLoggingService.Instance.WriteLog("Reached frmDelivery.BarcodeReader_ReadNotify");
    Symbol.Barcode.ReaderData TheReaderData = this.barcodeReader.GetNextReaderData();
    // If it is a successful read (as opposed to a failed one)
    if (TheReaderData.Result == Symbol.Results.SUCCESS)
    {
        // Handle the data from this read
        this.HandleData(TheReaderData);
        // Start the next read
        this.StartRead();
    }
}
private void ReaderForm_Activated(object sender, EventArgs e)
{
    ExceptionLoggingService.Instance.WriteLog("Reached frmDelivery.ReaderForm_Activated");
    // If there are no reads pending on barcodeReader start a new read
    if (!this.barcodeReaderData.IsPending)
    {
        this.StartRead();
    }
}
private void ReaderForm_Deactivate(object sender, EventArgs e)
{
    ExceptionLoggingService.Instance.WriteLog("Reached frmDelivery.ReaderForm_Deactivate");
    this.StopRead();
}
private void HandleData(Symbol.Barcode.ReaderData readerData)
{
    ExceptionLoggingService.Instance.WriteLog("Reached frmDelivery.HandleData");
    textBoxUPC_PLU.Text = readerData.Text;
    // now move off of it to next non-read-only textBox
    textBoxPackSize.Focus();
}
private void StopRead()
{
    ExceptionLoggingService.Instance.WriteLog("Reached frmDelivery.StopRead");
    // If we have a reader
    if (this.barcodeReader != null)
    {
        // Flush (Cancel all pending reads)
        this.barcodeReader.ReadNotify -= this.barcodeEventHandler;
        this.barcodeReader.Actions.Flush();
    }
}
private void textBoxUPC_PLU_LostFocus(object sender, EventArgs e)
{
    ExceptionLoggingService.Instance.WriteLog("Reached frmDelivery.textBoxUPC_PLU_LostFocus");
    this.DisposeBarcodeReaderAndData();
}
private void DisposeBarcodeReaderAndData()
{
    ExceptionLoggingService.Instance.WriteLog("Reached frmDelivery.DisposeBarcodeReaderAndData");
    // If we have a reader
    if (this.barcodeReader != null)
    {
        // Disable the reader
        this.barcodeReader.Actions.Disable();
        // Free it up
        this.barcodeReader.Dispose();
        // Indicate we no longer have one
        this.barcodeReader = null;
    }
    // If we have a reader data
    if (this.barcodeReaderData != null)
    {
        // Free it up
        this.barcodeReaderData.Dispose();
        // Indicate we no longer have one
        this.barcodeReaderData = null;
    }
}

。这是在异常发生之前调用的代码。记录了"已到达frmDelivery.buttonSave_Click",我确实看到"已保存交货",但此后应用程序立即崩溃:

private void buttonSave_Click(object sender, EventArgs args)
{
    ExceptionLoggingService.Instance.WriteLog("Reached frmDelivery.buttonSave_Click");
    if (RequiredDataMissing())
    {
        this.IndicateMissingData();
        return;
    }
    this.PrepareForNewDSDTable();
    SaveDSDHeaderRecord();
    SaveWorkTableRecord();
    // Now can search the record
    buttonFind.Enabled = true;
    MessageBox.Show("Delivery saved");
}

。以下是日志文件的摘录(从调用 SaveWorkTableRecord() 到"洪水"):

Date: 3/13/2009 6:41:34 PM
Message: Reached frmDelivery.SaveWorkTableRecord
Date: 3/13/2009 6:41:34 PM
Message: Reached HHSUtils.TryConvertToInt32
Date: 3/13/2009 6:41:34 PM
Message: Reached HHSUtils.TryConvertToDecimal
Date: 3/13/2009 6:41:34 PM
Message: Reached SQliteHHSDBUtils.InsertWorkTableRecord
Date: 3/13/2009 6:41:34 PM
Message: Reached HHSUtils.GetDBConnection
Date: 3/13/2009 6:41:34 PM
Message: Reached frmDelivery.ReaderForm_Deactivate
Date: 3/13/2009 6:41:34 PM
Message: Reached frmDelivery.StopRead
Date: 3/13/2009 6:41:37 PM
Message: Reached frmDelivery.ReaderForm_Activated
Date: 3/13/2009 6:41:37 PM
Message: From application-wide exception handler: System.NullReferenceException: NullReferenceException
   at HHS.FrmDelivery.ReaderForm_Activated(Object sender, EventArgs e)
   at System.Windows.Forms.Form.OnActivated(EventArgs e)
   at System.Windows.Forms.Form.WnProc(WM wm, Int32 wParam, Int32 lParam)
   at System.Windows.Forms.Control._InternalWnProc(WM wm, Int32 wParam, Int32 lParam)
   at Microsoft.AGL.Forms.DLG.MessageBox(String wszCaption, String wszBody, MessageBoxButtons mbtyp, MessageBoxIcon mbicon, MessageBoxDefaultButton defbtn, DialogResult& mbret)
   at System.Windows.Forms.MessageBox.Show(String text, String caption, MessageBoxButtons buttons, MessageBoxIcon icon, MessageBoxDefaultButton defaultButton)
   at HHS.FrmDelivery.buttonSave_Click(Object sender, EventArgs args)
   at System.Windows.Forms.Control.OnClick(EventArgs e)
   at System.Windows.Forms.Button.OnClick(EventArgs e)
   at System.Windows.Forms.ButtonBase.WnProc(WM wm, Int32 wParam, Int32 lParam)
   at System.Windows.Forms.Control._InternalWnProc(WM wm, Int32 wParam, Int32 lParam)
   at Microsoft.AGL.Forms.EVL.EnterMainLoop(IntPtr hwnMain)
   at System.Windows.Forms.Application.Run(Form fm)
   at HHS.Program.Main()

不要注意日期;手持设备(有点合适)是过去的生活。

下面是最后一个成功调用的方法:

private void SaveWorkTableRecord()
{
    ExceptionLoggingService.Instance.WriteLog("Reached frmDelivery.SaveWorkTableRecord");
    WorkTable wt = new WorkTable
                       {
                           WTName = this.dsdName,
                           SiteNum = this.nd.SiteNum,
                           FileType = "DSD",
                           FileDate = this.nd.DeliveryDate,
                           TotalItems = HHSUtils.TryConvertToInt32(this.textBoxQty.Text.Trim()),
                           TotalAmount = 
HHSUtils.TryConvertToDecimal(this.textBoxTotalDollar.Text.Trim())
                       };
    hhsdbutils.InsertWorkTableRecord(wt);
}

那么,为什么 barcodeReader 和/或 barcodeReaderData(显然)为空,当它们在 InitReader() 中实例化时,在构造表单时调用?

更新

即使条形码阅读

器和条形码阅读器数据代码从它的位置移动到 FormClosesing(),我仍然得到一个 NRE:

Date: 3/13/2009 8:10:08 PM
Message: Reached frmDelivery.DisposeBarcodeReaderAndData
Date: 3/13/2009 8:10:08 PM
Message: Reached HHSUtils.TextBoxLostFocus
Date: 3/13/2009 8:10:08 PM
Message: Reached frmDelivery.buttonClose_Click
Date: 3/13/2009 8:10:12 PM
Message: Reached frmDelivery.ReaderForm_Deactivate
Date: 3/13/2009 8:10:12 PM
Message: Reached frmDelivery.StopRead
Date: 3/13/2009 8:10:13 PM
Message: Reached frmDelivery.BarcodeReader_ReadNotify
Date: 3/13/2009 8:10:13 PM
Message: From application-wide exception handler: System.NullReferenceException: NullReferenceException
   at HHS.FrmDelivery.BarcodeReader_ReadNotify(Object sender, EventArgs e)
   at System.Windows.Forms.Control.TASK.Invoke()
   at System.Windows.Forms.Control._InvokeAll()

更新 2

更新:我将此代码移动到 FormClosesing(),但随后在关闭应用程序时获得了 NRE...?!?注释代码(条形码阅读器和条形码阅读器数据不再在任何地方被处置/无效)纠正了这个问题 - 不再有NRE。

为什么在成功操作后会发生此 NRE

注释掉释放 barcodeReader 和 barcodeReaderData 对象的代码可以解决问题:

private void DisposeBarcodeReaderAndData()
{
    ExceptionLoggingService.Instance.WriteLog("Reached frmDelivery.DisposeBarcodeReaderAndData");
    // Commenting out to see if this prevents the NRE; if so, try moving this to FromClose or FormClosing or something similar
    //// If we have a reader
    //if (this.barcodeReader != null)
    //{
    //    // Disable the reader
    //    this.barcodeReader.Actions.Disable();
    //    // Free it up
    //    this.barcodeReader.Dispose();
    //    // Indicate we no longer have one
    //    this.barcodeReader = null;
    //}
    //// If we have a reader data
    //if (this.barcodeReaderData != null)
    //{
    //    // Free it up
    //    this.barcodeReaderData.Dispose();
    //    // Indicate we no longer have one
    //    this.barcodeReaderData = null;
    //}
}

。但是我应该在表单关闭或表单关闭上处置/取消这些,还是到那时没有意义?

更新:我将此代码移动到 FormClosesing(),但随后在关闭应用程序时获得了 NRE...?!?注释代码(条形码阅读器和条形码阅读器数据不再在任何地方被处置/无效)纠正了这个问题 - 不再有NRE。