我调用了一个" Find"来自FrmDelivery的表格。尝试将条形码扫描到编辑框时,查找表单崩溃(相同的代码在应用程序的其他位置正常工作,例如在FrmDelivery中)。
日志文件显示FrmDelivery是遇到异常的表单:
Message: Reached frmDelivery.StartRead
Date: 2/19/2015 7:39:39 PM
Message: From FrmDelivery.StartRead(): The scanner not enabled, Call Enable() first.; Inner Ex: ; Stack Trace: at
Symbol.Barcode.Actions.Read(ReaderData rd)
然而,在打开查找表单之前,我关闭了FrmDelivery("这个"在下面):
private void buttonFind_Click(object sender, EventArgs e)
{
ExceptionLoggingService.Instance.WriteLog("Reached frmDelivery.buttonFind_Click");
this.Close(); // Close the Delivery form; this still leaves frmMain up
const HHSConsts.RecordTypes rt = HHSConsts.RecordTypes.Delivery;
frmFind ff = new frmFind(rt, dsdName);
ff.ShowDialog();
}
StartRead()是抛出异常的方法:
private void StartRead()
{
ExceptionLoggingService.Instance.WriteLog("Reached
frmDelivery.StartRead");
try
{
// If we have both a reader and a reader data
if ((this.barcodeReader != null) && (this.barcodeReaderData !=
null))
{
if (this.barcodeReaderData.IsPending) return;
// Submit a read
this.barcodeReader.ReadNotify += this.barcodeEventHandler;
this.barcodeReader.Actions.Read(this.barcodeReaderData);
}
}
catch (Exception ex)
{
String msgInnerExAndStackTrace = String.Format(
"{0}; Inner Ex: {1}; Stack Trace: {2}", ex.Message,
ex.InnerException, ex.StackTrace);
ExceptionLoggingService.Instance.WriteLog(String.Format("From
FrmDelivery.StartRead(): {0}", msgInnerExAndStackTrace));
}
}
//在FrmDelivery中调用StartRead()四个位置:
private void textBoxUPC_PLU_GotFocus(object sender, EventArgs e)
{
textBoxUPC_PLU.BackColor = HHSConsts.BARSCAN_COLOR; // Why is this
not sticking?
ExceptionLoggingService.Instance.WriteLog("Reached
frmDelivery.textBoxUPC_PLU_GotFocus");
if (this.InitReader())
{
this.StartRead();
}
}
private void BarcodeReader_ReadNotify(object sender, EventArgs e)
{
ExceptionLoggingService.Instance.WriteLog("Reached
frmDelivery.BarcodeReader_ReadNotify");
try
{
Symbol.Barcode.ReaderData TheReaderData =
this.barcodeReader.GetNextReaderData();
if (TheReaderData.Result == Symbol.Results.SUCCESS)
{
// Handle the data from this read
this.HandleData(TheReaderData);
// Start the next read
this.StartRead();
}
}
catch (Exception ex)
{
String msgInnerExAndStackTrace = String.Format(
"{0}; Inner Ex: {1}; Stack Trace: {2}", ex.Message,
ex.InnerException, ex.StackTrace);
ExceptionLoggingService.Instance.WriteLog(String.Format("From
FrmDelivery.BarcodeReader_ReadNotify(): {0}",
msgInnerExAndStackTrace));
}
}
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 textBoxId_GotFocus(object sender, EventArgs e)
{
ExceptionLoggingService.Instance.WriteLog("Reached
frmDelivery.textBoxId_GotFocus");
if (this.InitReader())
{
this.StartRead();
}
}
但是,在表单关闭后,这些方法的任何怎么能调用StartRead()?
答案 0 :(得分:1)
...在表单关闭后,这些方法中的任何一个如何调用StartRead()?
这取决于。条形码阅读器对象还在吗?即它是由任何东西引用的吗?
关闭表单会执行以下两种操作之一,具体取决于它是否为模态:隐藏窗口(对于模态窗口),或关闭并处理窗口(对于非模态窗口)。这几乎是你所保证的(不包括你添加的其他逻辑,例如FormClosed
事件处理程序。)
特别是,关闭表单不会以任何方式 本身导致该对象被垃圾收集或以其他方式禁用。许多表单仅由Winforms框架引用,并且在关闭时,这些引用将被丢弃。但是如果你做任何事情导致你的表格在其他地方被引用,那么它将继续存在。
您的FrmDelivery
表单似乎已订阅条形码阅读器对象的ReadNotify
事件。这涉及将委托实例添加到事件的调用列表中,并且由于事件处理程序方法是实例方法,因此该委托实例包含对FrmDelivery
对象的引用。
只要条形码阅读器对象仍然可以访问(或者它是static
类,因此它的所有成员都可以访问),这意味着您的FrmDelivery
对象仍然可以访问。也就是说,条形码阅读器对象保留委托对象,而委托对象又引用FrmDelivery
对象。
由于您的事件处理程序方法实际上是调用StartRead()
方法的方法之一,因此实际上这很可能是正在发生的事情。你的代码示例中没有足够的上下文来让任何阅读它的人绝对肯定,但概率非常高。这是一个不错的选择。 :)
顺便说一句,除了事件处理程序订阅(从问题描述中看起来它会保持FrmDelivery
对象仍然存在),您似乎以的方式嵌套ShowDialog()
调用也会阻止收集FrmDelivery
对象。
具体来说:您在窗体上的按钮的事件处理程序中的Close()
对象上调用FrmDelivery
。在该处理程序中的ShowDialog()
方法调用返回之前,该处理程序不会返回,并且在处理程序返回之前,对ShowDialog()
窗口的原始FrmDelivery
调用无法返回,直到{ {1}}调用返回,该方法的调用者无法处置或以其他方式丢弃表单实例。
这与事件处理程序本身是否被调用无关,但它确实会对对象的生命周期产生影响。