1. 程式人生 > >在創建窗口句柄之前,不能在控件上調用 Invoke 或 BeginInvoke

在創建窗口句柄之前,不能在控件上調用 Invoke 或 BeginInvoke

http 適合 parent req tle bar 可能 isp sign

今天關閉一個窗體,報出這樣的一個錯誤"在創建窗口句柄之前,不能在控件上調用 Invoke 或 BeginInvoke。",這個不用多想,肯定是那個地方沒有釋放掉。
既然碰到這個問題,先不說問題本身,來說說其他的一些事情。
winform最常見的是datagridview這個控件,不管重寫還是怎麽,很多數據的操作都是用datagridview來展示的,因此,它的異步調用也算是比較多的一類了。
比如:
1 從數據庫中讀取大量數據(所謂的分頁讀取不在這個範疇)
2 操作datagridview,然後一段時間後改變或者填充dtagridview
3 datagridview本身的一些效果,比如旋轉的延時等待,或者其他
不用異步肯定會出現死機的情況,用了異步可能也要註意一些情況

一個簡單的例子:
一個showdialog窗體裏有個一個datagridview,我用異步讀取數據,但是沒讀完,我關了窗體,這時候,數據讀完了,要執行
datagridview.source=??
這個時候,會出錯,可能不是"在創建窗口句柄之前,不能在控件上調用 Invoke 或 BeginInvoke。"這個錯誤,而是"資源已經釋放之類的",那咱們看看下面的幾個方法。
1 this.components 這個屬性

 /// <summary>
        /// Required designer variable.
        /// </summary>
        private System.ComponentModel.IContainer components = null;

每一個Designer.cs裏都有一個這個東西,IContainer接口相當於是一個容器,一個頁面全部的東西都會放在裏面,你拖一個button或者label都會放在裏面,筆者覺得,這個其實就是wpf的一個容器的概念,你可以從root尋找到每一個控件,而IContainer也可以找到你想要的控件,Active激活或者不激活會用到這個。
窗體釋放,components 也會釋放

技術分享圖片
 /// <summary>
        /// Clean up any resources being used.
        /// </summary>
        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }
技術分享圖片

這個方法會釋放,所以可以當做判斷窗體是否釋放的一個依據,但是筆者不推舉

2 this.IsDisposed
這個是判斷是否已經釋放了,用這個判斷比 components 要好一些,具體的原因是components在窗體關閉後可能沒有釋放,而this.IsDisposed窗體必然已經釋放了,當窗體是MID模式的時候,由於線程或其他原因,窗體的關閉可能不會釋放

3 IsHandleCreated
句柄是否創建
當子空間句柄創建了,而它的parent的句柄由於其他原因沒有創建或者已經釋放了,則也會出現其他問題,所以這個可以通過Parent.IsHandleCereated來盤點父句柄是否存在或者已經創建

上面幾個方法可以組合用,筆者判斷的時候差不多用後兩個
現在說說這兩個Invoke 和 BeginInvoke
Control.Invoke:在擁有此控件的線程上先進先出順序執行委托
Control.BeginInvoke:在擁有此控件線程上異步執行委托,也就是可能並非順序執行,這個有點熟悉,貌似說過了

最後說說解決方法:
在Invoke(....)之前加上1 this.components==null 2 this.IsDisposed 3 IsHandleCreated 來return 不執行invoke就可以,當然只是我針對自己遇到的解決的,可能並不適合其他的,但是總不會脫離其中

技術分享圖片
 set
            {
                if (IsDisposed ||!this.Parent.IsHandleCreated) return;

                this.Invoke((System.Action)delegate()
                {
                  
                });

            }
技術分享圖片

轉-https://www.cnblogs.com/fish124423/archive/2012/10/16/2726543.html

在創建窗口句柄之前,不能在控件上調用 Invoke 或 BeginInvoke