是否有可能触发封闭形式的事件?
Is it possible for a closed form's events to fire?
我从 FrmDelivery 调用了一个 "Find" 表单。查找表单在尝试将条形码扫描到编辑框中时崩溃(相同的代码在应用程序的其他地方工作正常,例如在 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(下面的"this"):
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));
}
}
// StartRead()在FrmDelivery中调用了四个地方:
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()?
…how could any of these methods call StartRead() after the form has been closed?
这取决于。条形码 reader 对象还在吗? IE。它被任何东西引用了吗?
关闭表单会执行以下两项操作之一,具体取决于它是否为模态:隐藏 window(对于模态 windows),或关闭并处理 window (对于非模态windows)。这几乎就是您可以保证的全部内容(不包括您添加的其他逻辑,例如 FormClosed
事件处理程序)。
特别是,关闭表单 不会 以任何方式本身导致该对象被垃圾收集或以其他方式禁用。许多窗体仅由 Winforms 框架引用,关闭时,这些引用将被丢弃。但是,如果您采取任何措施使您的表单在其他地方被引用,它就会继续存在。
您的 FrmDelivery
表单似乎订阅了条码 reader 对象的 ReadNotify
事件。这涉及将委托实例添加到事件的调用列表中,并且由于事件处理程序方法是实例方法,因此该委托实例包含对 FrmDelivery
对象的引用。
只要条形码 reader 对象仍然可以访问(或者如果它是 static
class,因此它的所有成员始终可以访问),这意味着您的 FrmDelivery
对象仍然可以访问。也就是说,条形码 reader 对象保留委托对象,委托对象又引用 FrmDelivery
对象。
由于您的事件处理程序方法实际上是可以调用您的 StartRead()
方法的方式之一,因此这很可能就是实际发生的情况。您的代码示例中没有足够的上下文让阅读它的人绝对确定,但可能性非常高。这是一个不错的选择。 :)
顺便说一句,除了事件处理程序订阅(从问题描述来看,它看起来无论如何都会使 FrmDelivery
对象保持活动状态),您似乎正在以 [=46] 的方式嵌套 ShowDialog()
调用=]也会阻止收集FrmDelivery
对象。
具体来说:您在表单按钮的事件处理程序中的 FrmDelivery
对象上调用 Close()
。在该处理程序 return 中调用 ShowDialog()
方法之前,该处理程序不会 return,并且在处理程序 return 之前,您最初的 ShowDialog()
调用 FrmDelivery
window 不能 return,并且在 ShowDialog()
调用 return 之前,该方法的调用者不能处理或丢弃表单实例.
这与事件处理程序本身是否被调用无关,但它确实对对象的生命周期有影响。
我从 FrmDelivery 调用了一个 "Find" 表单。查找表单在尝试将条形码扫描到编辑框中时崩溃(相同的代码在应用程序的其他地方工作正常,例如在 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(下面的"this"):
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));
}
}
// StartRead()在FrmDelivery中调用了四个地方:
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()?
…how could any of these methods call StartRead() after the form has been closed?
这取决于。条形码 reader 对象还在吗? IE。它被任何东西引用了吗?
关闭表单会执行以下两项操作之一,具体取决于它是否为模态:隐藏 window(对于模态 windows),或关闭并处理 window (对于非模态windows)。这几乎就是您可以保证的全部内容(不包括您添加的其他逻辑,例如 FormClosed
事件处理程序)。
特别是,关闭表单 不会 以任何方式本身导致该对象被垃圾收集或以其他方式禁用。许多窗体仅由 Winforms 框架引用,关闭时,这些引用将被丢弃。但是,如果您采取任何措施使您的表单在其他地方被引用,它就会继续存在。
您的 FrmDelivery
表单似乎订阅了条码 reader 对象的 ReadNotify
事件。这涉及将委托实例添加到事件的调用列表中,并且由于事件处理程序方法是实例方法,因此该委托实例包含对 FrmDelivery
对象的引用。
只要条形码 reader 对象仍然可以访问(或者如果它是 static
class,因此它的所有成员始终可以访问),这意味着您的 FrmDelivery
对象仍然可以访问。也就是说,条形码 reader 对象保留委托对象,委托对象又引用 FrmDelivery
对象。
由于您的事件处理程序方法实际上是可以调用您的 StartRead()
方法的方式之一,因此这很可能就是实际发生的情况。您的代码示例中没有足够的上下文让阅读它的人绝对确定,但可能性非常高。这是一个不错的选择。 :)
顺便说一句,除了事件处理程序订阅(从问题描述来看,它看起来无论如何都会使 FrmDelivery
对象保持活动状态),您似乎正在以 [=46] 的方式嵌套 ShowDialog()
调用=]也会阻止收集FrmDelivery
对象。
具体来说:您在表单按钮的事件处理程序中的 FrmDelivery
对象上调用 Close()
。在该处理程序 return 中调用 ShowDialog()
方法之前,该处理程序不会 return,并且在处理程序 return 之前,您最初的 ShowDialog()
调用 FrmDelivery
window 不能 return,并且在 ShowDialog()
调用 return 之前,该方法的调用者不能处理或丢弃表单实例.
这与事件处理程序本身是否被调用无关,但它确实对对象的生命周期有影响。