封闭形式的事件是否有可能被解雇?

时间:2015-02-20 00:57:15

标签: c# forms barcode barcode-scanner scanning

我调用了一个" 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()?

1 个答案:

答案 0 :(得分:1)

  

...在表单关闭后,这些方法中的任何一个如何调用StartRead()?

这取决于。条形码阅读器对象还在吗?即它是由任何东西引用的吗?

关闭表单会执行以下两种操作之一,具体取决于它是否为模态:隐藏窗口(对于模态窗口),或关闭并处理窗口(对于非模态窗口)。这几乎是你所保证的(不包括你添加的其他逻辑,例如FormClosed事件处理程序。)

特别是,关闭表单不会以任何方式 本身导致该对象被垃圾收集或以其他方式禁用。许多表单仅由Winforms框架引用,并且在关闭时,这些引用将被丢弃。但是如果你做任何事情导致你的表格在其他地方被引用,那么它将继续存在。

您的FrmDelivery表单似乎已订阅条形码阅读器对象的ReadNotify事件。这涉及将委托实例添加到事件的调用列表中,并且由于事件处理程序方法是实例方法,因此该委托实例包含对FrmDelivery对象的引用。

只要条形码阅读器对象仍然可以访问(或者它是static类,因此它的所有成员都可以访问),这意味着您的FrmDelivery对象仍然可以访问。也就是说,条形码阅读器对象保留委托对象,而委托对象又引用FrmDelivery对象。

由于您的事件处理程序方法实际上是调用StartRead()方法的方法之一,因此实际上这很可能是正在发生的事情。你的代码示例中没有足够的上下文来让任何阅读它的人绝对肯定,但概率非常高。这是一个不错的选择。 :)


顺便说一句,除了事件处理程序订阅(从问题描述中看起来它会保持FrmDelivery对象仍然存在),您似乎以的方式嵌套ShowDialog()调用也会阻止收集FrmDelivery对象。

具体来说:您在窗体上的按钮的事件处理程序中的Close()对象上调用FrmDelivery。在该处理程序中的ShowDialog()方法调用返回之前,该处理程序不会返回,并且在处理程序返回之前,对ShowDialog()窗口的原始FrmDelivery调用无法返回,直到{ {1}}调用返回,该方法的调用者无法处置或以其他方式丢弃表单实例。

这与事件处理程序本身是否被调用无关,但它确实会对对象的生命周期产生影响。