Why is the previous form blocking the new form?

六眼飞鱼酱① 提交于 2020-01-06 13:00:06

问题


I am trying to open one form from another, closing the original form. This is standard stuff; I've done in doubtless hundreds of times over the years. Yet in this case, it's not working -- the previous form does not close - I see a piece of the new form "shining through" the old, and the caption changes from "Delivery" (original form) to "Find" (new form), but the controls on the "Find" form never display and, in fact, in a few seconds the app crashes, as if all its resources have been disposed of or something - it simply closes down/goes away. ???

Here is the "from" from at runtime, just before trying to open the next ("Find") form via the Find button:

Here is the code behind the "Find" button:

private void buttonFind_Click(object sender, EventArgs e)
{
    const HHSConsts.RecordTypes rt = HHSConsts.RecordTypes.Delivery;
    frmFind ff = new frmFind(rt, dsdName);
    ff.Show();
    this.Close();
}

Here is the (overloaded) constructor for the "Find" form:

public frmFind(HHSConsts.RecordTypes rt, String tableName)
{
    InitializeComponent();
    _rt = rt;
    _tableName = tableName;
}

And here is what I see when I hit the "Find" button:

(for awhile, then it disappears).

This is the design-time appearance of the "Find" form:

So it seems the gold TextBox on the "Find" form is trying to "shine through" but...what the heck?

My log file, which catches exception messages, contains this:

Date: 3/19/2009 2:14:26 AM
Message: Reached frmDelivery.buttonFind_Click

Date: 3/19/2009 2:14:26 AM
Message: Reached frmDelivery.ReaderForm_Deactivate

Date: 3/19/2009 2:14:26 AM
Message: Reached frmDelivery.StopRead

Date: 3/19/2009 2:14:26 AM
Message: Reached frmFind.textBoxScan_GotFocus

Date: 3/19/2009 2:14:26 AM
Message: Reached frmFind.InitReader

Date: 3/19/2009 2:14:27 AM
Message: From application-wide exception handler: Symbol.Exceptions.OperationFailureException:     
    SCAN_GetInterfaceParams
   at Symbol.Barcode.InterfaceParams.GetInterfaceParams()
   at Symbol.Barcode.InterfaceParams..ctor(Reader reader)
   at Symbol.Barcode.Actions.Enable()
   at HHS.frmFind.InitReader()
   at HHS.frmFind.textBoxScan_GotFocus(Object sender, EventArgs e)
   at System.Windows.Forms.Control.OnGotFocus(EventArgs e)
   at System.Windows.Forms.Control.WnProc(WM wm, Int32 wParam, Int32 lParam)
   at System.Windows.Forms.Control._InternalWnProc(WM wm, Int32 wParam, Int32 lParam)
   at Microsoft.AGL.Forms.WL.SetVis(IntPtr hwnThis, BOOL fVis)
   at System.Windows.Forms.Control.set_Visible(Boolean value)
   at HHS.FrmDelivery.buttonFind_Click(Object sender, EventArgs e)
   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()

So initReader is a problem? It's this:

private bool InitReader()
{
    ExceptionLoggingService.Instance.WriteLog("Reached frmFind.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;
}

...and the same exact code is in all the other forms that use a TextBox for barcode scanning (without this problem on opening them). In fact, FrmDelivery has this exact same code. Is it perhaps because I had commented out this code in FrmDelivery:

private void FrmDelivery_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
    //// 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;
    //}
}

? (I had to do so to prevent a previous exception; see this)

Even if InitReader is the problem, why would it chuck such an outsized spanner into the appearance of the forms?

UPDATE

I thought maybe the problem was with the barcode reading code; I added code to dispose and nullify some barcode objects, which had been causing problems when called from the Form Closing event, to the "Find" button code:

private void buttonFind_Click(object sender, EventArgs e)
{
    // See if this solves the explosion of the find form
    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;
    }

    const HHSConsts.RecordTypes rt = HHSConsts.RecordTypes.Delivery;
    frmFind ff = new frmFind(rt, dsdName);
    ff.ShowDialog();
}

However this only makes matters (slightly) worse: now the Find form doesn't display at all. Instead of it partially displaying and, after a few seconds, the app shutting down, now I see an hourglass for a few seconds, the Find form doesn't display at all, and the app shuts down.

UPDATE 2

I find that if I comment out textBoxScan_GotFocus on the Find form, it displays pretty much (but not completely) as it should:

It's as if I hear the Find form singing "I once was lost, and now I'm f..."; it's a mystery to me (not a Fleetwood Mac reference) that a piece of the form is playing hard to see...and, of course, commenting out the textBoxScan_GotFocus code makes the textbox "deaf" to barcode scans, so it's not really a viable fix...

UPDATE 3

The problem seems to be with the barcode scanning classes. If I open the Find form first (without first opening another form that has barcode scanning code), there is no crash (the form still has an obscured portion, as seen above, for some reason, but the app doesn't crash).

So, it seems that once Symbol.Barcode.Reader and/or Symbol.Barcode.ReaderData are used (e.g., by FrmDelivery), they are unstable when trying to use them again in frmFind. If I bypass FrmDelivery and go straight to frmFind, there's not a problem.

So the "OperationFailureException" has something to do, I suspect, with the barcode stuff not being cleaned up properly. Do I need to make Symbol.Barcode.Reader barcodeReader and Symbol.Barcode.ReaderData barcodeReaderData global, rather than have them in each form that uses them, or what?

UPDATE 4

I tried calling this in the "Find" form from the scanning text box's GotFocus() event:

private void DisposeBarcodeReaderAndData()
{
    ExceptionLoggingService.Instance.WriteLog("Reached frmFind.DisposeBarcodeReaderAndData");
    if (this.barcodeReader != null)
    {
        ExceptionLoggingService.Instance.WriteLog("barcodeReader was not null");
        // Disable the reader
        this.barcodeReader.Actions.Disable();
        // Free it up
        this.barcodeReader.Dispose();
        // Indicate we no longer have one
        this.barcodeReader = null;
    }

    if (this.barcodeReaderData != null)
    {
        ExceptionLoggingService.Instance.WriteLog("barcodeReaderData was not null");
        // Free it up
        this.barcodeReaderData.Dispose();
        // Indicate we no longer have one
        this.barcodeReaderData = null;
    }
}

...but, as expected (after all, barcodeReader and barcodeReaderData are members of this form, and should not have been anything but null), the "was not null" msgs are not written to the log file, and calling this code makes no difference in the app's behavior.

I still think it's something to do with Symbol.Barcode assembly stuff still being resident in memory, though. Is there a way to forcibly unload a DLL (Symbol.Barcode) so that further references to it cause a "fresh" version of it to be instantiated and used?

来源:https://stackoverflow.com/questions/27698194/why-is-the-previous-form-blocking-the-new-form

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!