您現在的位置: 365建站網 > 365學習 > C#/vb.net在創建窗口句柄之前,不能在控件上調用 Invoke 或 BeginInvoke錯誤的解決辦法

C#/vb.net在創建窗口句柄之前,不能在控件上調用 Invoke 或 BeginInvoke錯誤的解決辦法

文章來源:365jz.com     點擊數:493    更新時間:2020-06-29 15:47   參與評論

C#/vb.net在創建窗口句柄之前,不能在控件上調用 Invoke 或 BeginInvoke錯誤的解決辦法

情況:在C#開發的過程中多線程委托是經常用的,今天在測試以前寫的軟件的時候發現有個問題,報 在創建窗口句柄之前,不能在控件上調用 Invoke 或 BeginInvoke。 這樣的錯誤。

最近在所項目時,在耗時線程中,需要實時刷新界面進度,每次第一次都能成功顯示進度,但是關閉窗口后,再次打開程序執行,則刷新失敗,報錯:在創建窗口句柄之前,不能在控件上調用 Invoke 或 BeginInvoke。

試過多種方案無果!困擾許久!

問題的根本在于窗口沒有完全釋放!

今天偶爾發現,窗口在創建時會添加事件,當我們關閉程序且沒有注銷事件!我在窗口關閉時注銷事件后,再次打開成功打開。問題解決!

 private void button5_Click(object sender, EventArgs e)
        {
            if (Form_ROI == null)
            {
                Form_ROI = new ROI(this);
                Form_ROI.StartPosition = FormStartPosition.CenterParent;
                this.TransfEvent += Form_ROI.frm_TransfEvent; //問題在這,調用窗體的時候注冊了事件
                Form_ROI.Show();
                //Form_ROI.ShowDialog();
            }
        }



解決方法:關閉窗體的時候,注銷事件


        private void ROI_FormClosing(object sender, FormClosingEventArgs e)
        {
            fm1.Form_ROI = null;
            fm1.TransfEvent -= this.frm_TransfEvent; //解決方法,注銷掉事件
        }


另外解決方法:加上 if (this.IsHandleCreated)


1、首先分析問題,

句柄:是對象的引用名,存于棧區(可以理解為對象的指針),對象是存于堆區,通過操控棧區的引用名來操控對象。

控件上調用 Invoke 或 BeginInvoke的作用:由于C#是是強制類型安全的,當調用方線程與控件的線程(一般位于主線程)不在同一個線程,則調用方需要使用Invoke 或 BeginInvoke方法來間接委托的使用主線程的控件。


報錯顯示“在創建窗口句柄之前,不能在控件上調用 Invoke 或 BeginInvoke”

說明在當前控件的容器窗口并關閉了,應該是使用鼠標關掉了一個子窗口,不存在了(棧中保存的該窗體引用名被清除), 但是該程序包含多個窗口,關掉了一個窗口,程序還是在運行,但是在程序中的一個線程還想使用關掉的窗體上的控件,窗體關閉了,其包含的控件對象也消失了,因此報錯。很可能是窗體關閉了,但是其線程還未執行完成消失。


2、這顯然是線程不知道該控件已經消失了,還繼續使用它造成的錯誤,因此我們在程序中添加 **if (this.IsHandleCreated)**判斷窗體或控件的句柄是否還存在,之后才使用控件。


在調用下一個委托的時候。先判斷下 在控件上面或者窗體上 IsHandleCreated ,如下:


if (this.IsHandleCreated)
{
    Methinvoker meth = new Methinvoker(MessSeInfo);
   this.BeginInvoke(meth);
}


1、如何獲得一個窗口的句柄?

    例如獲取窗口PictureBox控件(其他控件也可以)的句柄,

IntPtr handle = pictureBox.Handle;

2、注意:窗口創建和窗口創建完畢即有句柄完全是兩回事?。?!

    窗口創建時,窗口并沒有創建句柄,只有Application.Run(form)或者form.Show()之后才有句柄,即窗口只有顯示或者啟動消息循環后才有句柄!如果創建form之后Form. form. = new Form(),主線程中調用form.Handle,如果句柄尚未創建,引用該屬性將強制創建句柄,對系統內的邏輯將產生致命的影響。

    3、如何判斷一個窗口的句柄創建完畢?

    利用IsHandleCreated 屬性:此屬性指示控件是否有與他關聯的句柄,如果已經為控件分配了句柄,則為 true;否則為 false。

 4、一些屬性:

    (1)、CreateControl :強制創建控件,包括句柄和任何子控件

    (2)、CreateHandle :為該控件創建句柄,

     通常,不應該直接調用 CreateHandle 方法。首選的方法是調用CreateControl方法,此方法在創建控件時強制為該控件及其子控件創建一個句柄。給繼承者的說明 在派生類中重寫 CreateHandle 時,請確保調用了基類的 CreateHandle 方法,以便確保已創建該句柄。

    (3)、DestroyHandle :毀壞與該控件關聯的句柄

    (4)、FromChildHandle :檢索包含指定句柄的控件

    (5)、FromHandle :返回當前與指定句柄關聯的控件

    (6)、Handle :獲取控件綁定到的窗口句柄,Handle 屬性的值是 Windows HWND。如果句柄尚未創建,引用該屬性將強制創建句柄。

    (7)、IsHandleCreated :指示控件是否有與他關聯的句柄,如果已經為控件分配了句柄,則為 true;否則為 false。

    (8)、RecreateHandle :強制為控件重新創制句柄

    (9)、RecreatingHandle :指示當前是否在重創句柄

 5.注意:

    句柄是隨機量,兩次運行一般都會得到兩次不同的結果


如對本文有疑問,請提交到交流論壇,廣大熱心網友會為你解答??! 點擊進入論壇


發表評論 (493人查看,0條評論)
請自覺遵守互聯網相關的政策法規,嚴禁發布色情、暴力、反動的言論。
用戶名: 驗證碼: 點擊我更換圖片
最新評論
------分隔線----------------------------
自拍偷拍福力视频,偷拍国际精品,麻豆一区福利电影,国产网红视频午夜福利,se视频大全,久久国产AV影院 色窝窝色蝌蚪在线视频网站免费看| 免费少妇A级毛片| 亚洲av美国av产亚洲av图片| 宝贝你可真是个小荡货| 天天操天天干天天操视频| 诱人的女邻居2中文字幕| 女神被啪到深处娇喘在线观看| 午夜成年奭片免费观看在线| 吾福利爱导航| 18禁日本黄无遮挡禁动漫| 攻受男男肉不打码视频| 巨乳护士高清在线观看| a级毛片无码兔费真人久久| 美女裸乳无档视频免费| 玩弄漂亮少妇高潮大叫| 日韩视频无码日韩视频又2020| aⅴ中文无码亚洲| 少妇高潮ass| 所有免费的av网站| 成·人免费午夜无码视频蜜芽| 奇777四色影视在线看| 粗大老头让我欲仙欲死| 丁香婷婷六月亚洲色五月| by最新网站域名2021| 日本熟妇牲交视频| 青青青视频香蕉在线观看视频| 成在人线av无码免费高潮水| 么公又大又硬又粗又爽| 国产丝袜在线精品丝袜不卡| 一女多男同时进6根同时进行| 极品女主播流白浆喷水呻吟视频| http://www.wimaxwichitafalls.com