سؤال

I am maintaining a program with customer informations. It consists of many forms that each show some relevant info from the database. This error is in a single form after doing the following

  1. Open the customer search form
  2. View random customer A info in the customerinfo form
  3. open the crm form and it automatically shows customer A. Then add a file to him via draganddrop.
  4. Close the last two forms and select random customer B and do the same.
  5. Close the last two forms and select customer A and add a new file. Error!!!

Here is the code that fails:

private void FireFileCountChanged() {
    if (FileCountChanged != null)
        BeginInvoke(new DeferEvent(FireFileCountChangedDeferred), 2); // FAILS

"An unhandled exception of type 'System.InvalidOperationException' occurred in System.Windows.Forms.dll

Additional information: Invoke or BeginInvoke cannot be called on a control until the window handle has been created."

I tried adding the following:

private void FireFileCountChanged() {
        if (FileCountChanged != null && this.Handle != null) // CHANGED AND FAILS.
            BeginInvoke(new DeferEvent(FireFileCountChangedDeferred), 2);
    }

But the this.handle gives:

'this.Handle' threw an exception of type 'System.ObjectDisposedException' and "Cannot access a disposed object.\r\nObject name: 'AttachmentsControl'."

Then I added a timeout of 10 seconds as the first line in the method, but the handle is still not created. Has the handle somehow been disposed when one of the window were closed? And what can be done about this? Any help is appreciated. I'm kind of stuck.

private void FireFileCountChangedDeferred(int repostCount) {
    if (FileCountChanged != null) {
        if (repostCount > 0) {
            //black magic is somehow involved in getting this event to fire *after* the filewatcher reports the change.
            System.Threading.Thread.Sleep(10);
            BeginInvoke(new DeferEvent(FireFileCountChangedDeferred), repostCount - 1);
        } else
            FileCountChanged(this, null);
    }
}

private void CopyFiles(string[] files, bool reload) {
    if (CreatePath()) {
        foreach (string src in files) {
            try {
                string dest = MakeSafeFilename(src);
                File.Copy(src, dest);
                FireFileCountChanged();
            } catch (Exception ex) {
                //Util.Print("Copy ex: {0}", ex.Message);
                ErrMsg("Error while copying:{1}{0}", ex.Message, environment.NewLine);
            }
        }
    }
}

private void Lstv_DragDrop(object sender, DragEventArgs ea) {
    if (m_CanAdd) {
        string[] files = GetDraggedFiles(ea);
        if (files != null)
            CopyFiles(files, true);
        else if (OutlookDataObject.HoldsOutlookData(ea) && CreatePath()) {
            try {
                OutlookDataObject.CopyDroppedFiles(ea, m_Path, OutlookFilenameCallback);
            } catch (Exception ex) {
                //Util.Print("Copy ex: {0}", ex.Message);
                ErrMsg("Error copying from Outlook:{1}{0}", ex.Message, Environment.NewLine);
            }
        }
    }
}

Solution

private void FireFileCountChanged() {
                while (!this.IsHandleCreated) // added
                          System.Threading.Thread.Sleep(100); //added

    if (FileCountChanged != null)
        BeginInvoke(new DeferEvent(FireFileCountChangedDeferred), 2);
هل كانت مفيدة؟

المحلول

You need to check the IsHandleCreated property, not compare the Handle to null. Reading the Handle property is considered a UI operation itself.

private void FireFileCountChanged() {
    if (FileCountChanged != null && this.IsHandleCreated)
        BeginInvoke(new DeferEvent(FireFileCountChangedDeferred), 2);
}

However, based on the complex steps that you need to take to reproduce the bug, I suspect that there are some form instance re-use issues or other more complex issues at play here, and it isn't just a matter of making this call to BeginInvoke work.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top