为什么在成功操作后会发生此 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。
注释掉释放 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。