BeginInvoke失败,因为尚未创建窗口句柄

时间:2012-03-16 13:39:50

标签: c# handle begininvoke

我正在维护一个包含客户信息的程序。它由许多表单组成,每个表单都显示数据库中的一些相关信息。执行以下操作后,此错误采用单一形式

  1. 打开客户搜索表单
  2. 查看随机客户在customerinfo表单中的信息
  3. 打开crm表单,它会自动显示客户A.然后通过draganddrop向他添加一个文件。
  4. 关闭最后两个表单并选择随机客户B并执行相同操作。
  5. 关闭最后两个表单并选择客户A并添加新文件。错误!!!
  6. 以下是失败的代码:

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

    “System.Windows.Forms.dll中发生了'System.InvalidOperationException'类型的未处理异常

    其他信息:在创建窗口句柄之前,无法在控件上调用Invoke或BeginInvoke。“

    我尝试添加以下内容:

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

    但是this.handle给出了:

    'this.Handle'抛出了'System.ObjectDisposedException'类型的异常 “无法访问已处置的对象。\ r \ n对象名称:'AttachmentsControl'。”

    然后我在方法的第一行添加了10秒的超时,但仍然没有创建句柄。当其中一个窗户关闭时,手柄是否已被处理掉?那可以做些什么呢?任何帮助表示赞赏。我有点卡住了。

    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);
                }
            }
        }
    }
    

    解决方案

    private void FireFileCountChanged() {
                    while (!this.IsHandleCreated) // added
                              System.Threading.Thread.Sleep(100); //added
    
        if (FileCountChanged != null)
            BeginInvoke(new DeferEvent(FireFileCountChangedDeferred), 2);
    

1 个答案:

答案 0 :(得分:7)

您需要检查IsHandleCreated属性,而不是将Handle与null进行比较。读取Handle属性本身就被视为UI操作。

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

但是,基于重现错误需要采取的复杂步骤,我怀疑在这里有一些表单实例重用问题或其他更复杂的问题,这不仅仅是一个问题调用BeginInvoke工作。