青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

cc

  C++博客 :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::
  38 隨筆 :: 14 文章 :: 21 評論 :: 0 Trackbacks

 前段時間遇到跨線程調用窗體控件的問題,其實一句話System.Windows.Forms.Control.CheckForIllegalCrossThreadCalls = false;就可以解決,但感覺會有不穩定因素,因此在網上找了一些相應的文章感覺還不錯,第一種用的比較順手:

(注:在devexpress控件中用DevExpress.Data.CurrencyDataController.DisableThreadingProblemsDetection = true;)

    用戶不喜歡反應慢的程序。在執行耗時較長的操作時,使用多線程是明智之舉,它可以提高程序 UI 的響應速度,使得一切運行顯得更為快速。在 Windows 中進行多線程編程曾經是 C++ 開發人員的專屬特權,但是現在,可以使用所有兼容 Microsoft .NET 的語言來編寫。

不過Windows 窗體體系結構對線程使用制定了嚴格的規則。如果只是編寫單線程應用程序,則沒必要知道這些規則,這是因為單線程的代碼不可能違反這些規則。然而,一旦采用多線程,就需要理解 Windows 窗體中最重要的一條線程規則:除了極少數的例外情況,否則都不要在它的創建線程以外的線程中使用控件的任何成員。本規則的例外情況有文檔說明,但這樣的情況非常少。這適用于其類派生自 System.Windows.Forms.Control 的任何對象,其中幾乎包括 UI 中的所有元素。所有的 UI 元素(包括表單本身)都是從 Control 類派生的對象。此外,這條規則的結果是一個被包含的控件(如,包含在一個表單中的按鈕)必須與包含它控件位處于同一個線程中。也就是說,一個窗口中的所有控件屬于同一個 UI 線程。實際中,大部分 Windows 窗體應用程序最終都只有一個線程,所有 UI 活動都發生在這個線程上。這個線程通常稱為 UI 線程。這意味著您不能調用用戶界面中任意控件上的任何方法,除非在該方法的文檔說明中指出可以調用。該規則的例外情況(總有文檔記錄)非常少而且它們之間關系也不大。請注意,以下代碼是非法的:

        private Thread myThread;

        private void Form1_Load(object sender, EventArgs e)

        {

            myThread = new Thread(new ThreadStart(RunsOnWorkerThread));

            myThread.Start();

        }

        private void RunsOnWorkerThread()

        {

            label1.Text = "myThread線程調用UI控件";

    }

如果您在 .NET Framework 1.0 版本中嘗試運行這段代碼,也許會僥幸運行成功,或者初看起來是如此。這就是多線程錯誤中的主要問題,即它們并不會立即顯現出來。甚至當出現了一些錯誤時,在第一次演示程序之前一切看起來也都很正常。但不要搞錯 — 我剛才顯示的這段代碼明顯違反了規則,并且可以預見,任何抱希望于“試運行時良好,應該就沒有問題”的人在即將到來的調試期是會付出沉重代價的。

下面我們來看看有哪些方法可以解決這一問題。

一、System.Windows.Forms.MethodInvoker 類型是一個系統定義的委托,用于調用不帶參數的方法。
        private Thread myThread;

        private void Form1_Load(object sender, EventArgs e)

        {

            myThread = new Thread(new ThreadStart(RunsOnWorkerThread));

            myThread.Start();

        }

        private void RunsOnWorkerThread()

        {

            MethodInvoker mi = new MethodInvoker(SetControlsProp);

            BeginInvoke(mi);

        }

        private void SetControlsProp()

        {

            label1.Text = "myThread線程調用UI控件";

        }

 

二、直接用System.EventHandle(可帶參數)

        private Thread myThread;

        private void Form1_Load(object sender, EventArgs e)

        {

            myThread = new Thread(new ThreadStart(RunsOnWorkerThread));

            myThread.Start();

        }

        private void RunsOnWorkerThread()

        {

            //DoSomethingSlow();

            string pList = "myThread線程調用UI控件";

            label1.BeginInvoke(new System.EventHandler(UpdateUI), pList);

        }

        //直接用System.EventHandler,沒有必要自定義委托

        private void UpdateUI(object o, System.EventArgs e)

        {

           //UI線程設置label1屬性

            label1.Text = o.ToString() + "成功!";

        }

三、包裝 Control.Invoke

雖然第二個方法中的代碼解決了這個問題,但它相當繁瑣。如果輔助線程希望在結束時提供更多的反饋信息,而不是簡單地給出“Finished!”消息,則 BeginInvoke 過于復雜的使用方法會令人生畏。為了傳達其他消息,例如“正在處理”、“一切順利”等等,需要設法向 UpdateUI 函數傳遞一個參數。可能還需要添加一個進度欄以提高反饋能力。這么多次調用 BeginInvoke 可能導致輔助線程受該代碼支配。這樣不僅會造成不便,而且考慮到輔助線程與 UI 的協調性,這樣設計也不好。對這些進行分析之后,我們認為包裝函數可以解決這兩個問題。

        private Thread myThread;

        private void Form1_Load(object sender, EventArgs e)

        {

            myThread = new Thread(new ThreadStart(RunsOnWorkerThread));

            myThread.Start();

        }

        private void RunsOnWorkerThread()

        {

            ////DoSomethingSlow();

            for (int i = 0; i < 100; i++)

            {

                ShowProgress( Convert.ToString(i)+"%", i);

                Thread.Sleep(100);

            }

        }

        public void ShowProgress(string msg, int percentDone)

        {

            // Wrap the parameters in some EventArgs-derived custom class:

            System.EventArgs e = new MyProgressEvents(msg, percentDone);

            object[] pList = { this, e };

 

            BeginInvoke(new MyProgressEventsHandler(UpdateUI), pList);

        }

        private delegate void MyProgressEventsHandler(object sender, MyProgressEvents e);

        private void UpdateUI(object sender, MyProgressEvents e)

        {

            lblStatus.Text = e.Msg;

            myProgressControl.Value = e.PercentDone;

       }

    public class MyProgressEvents : EventArgs

    {

        public string Msg;

        public int PercentDone;

        public MyProgressEvents(string msg, int per)

        {

            Msg = msg;

            PercentDone = per;

        }

}

ShowProgress 方法對將調用引向正確線程的工作進行封裝。這意味著輔助線程代碼不再擔心需要過多關注 UI 細節,而只要定期調用 ShowProgress 即可。

如果我提供一個設計為可從任何線程調用的公共方法,則完全有可能某人會從 UI 線程調用這個方法。在這種情況下,沒必要調用 BeginInvoke,因為我已經處于正確的線程中。調用 Invoke 完全是浪費時間和資源,不如直接調用適當的方法。為了避免這種情況,Control 類將公開一個稱為 InvokeRequired 的屬性。這是“只限 UI 線程”規則的另一個例外。它可從任何線程讀取,如果調用線程是 UI 線程,則返回假,其他線程則返回真。這意味著我可以按以下方式修改包裝:

        public void ShowProgress(string msg, int percentDone)

        {

            if (InvokeRequired)

            {

                // As before

                //...

            }

            else

            {

                // We're already on the UI thread just

                // call straight through.

                UpdateUI(this, new MyProgressEvents(msg,PercentDone));

            }

        }

 

本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/jackey0517/archive/2009/09/08/4533458.aspx

posted on 2011-02-27 14:06 醒目西西 閱讀(1877) 評論(0)  編輯 收藏 引用
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            国产视频一区欧美| 久久综合色综合88| 久久视频免费观看| 久久疯狂做爰流白浆xx| 亚洲在线观看免费| 午夜精品剧场| 久久国产精品久久久久久| 亚洲欧美大片| 亚洲在线视频一区| 欧美在线一二三| 久久久亚洲高清| 日韩亚洲不卡在线| 99精品欧美| 欧美一区二区三区免费视| 欧美激情91| 亚洲日韩第九十九页| 欧美国产日韩二区| 亚洲一区二区三区四区五区午夜 | 欧美一区三区二区在线观看| 亚洲视频成人| 久久国产一区二区三区| 麻豆国产精品777777在线| 欧美国产精品va在线观看| 欧美日韩另类视频| 国产真实久久| 国产精品视频一区二区高潮| 国产偷国产偷亚洲高清97cao| 久久精品国产2020观看福利| 国产区日韩欧美| 久久精品国产999大香线蕉| 久久久久久久久久久成人| 一区二区日韩伦理片| aa国产精品| 性感少妇一区| 一本久道久久综合婷婷鲸鱼| 激情五月***国产精品| 亚洲日本电影| 欧美在线播放| 一本到12不卡视频在线dvd| 午夜一区二区三区不卡视频| 欧美激情日韩| 国内精品嫩模av私拍在线观看| 国产精品高清免费在线观看| 狠狠噜噜久久| 欧美影院成年免费版| 亚洲日本中文字幕免费在线不卡| 欧美91大片| 亚洲欧美国产一区二区三区| 欧美黄色影院| 欧美理论电影在线播放| 激情欧美一区| 久久不射中文字幕| 亚洲欧美日韩在线一区| 中文在线不卡| 欧美二区不卡| 久久全国免费视频| 国产综合色在线| 午夜精品久久久久久久久久久久| 亚洲视频999| 亚洲激情在线观看| 欧美成人黑人xx视频免费观看| 欧美国产在线电影| 欧美一区二区私人影院日本| 国产精品国色综合久久| 国产精品久久久久久亚洲毛片| 欧美日韩国产成人在线91| 欧美99久久| 又紧又大又爽精品一区二区| 久久久久成人网| 欧美一区二区三区精品电影| 国产亚洲精品自拍| 在线播放国产一区中文字幕剧情欧美| 激情自拍一区| 亚洲乱码国产乱码精品精可以看| 亚洲视频在线观看视频| 91久久国产综合久久91精品网站| 一区二区三区黄色| 午夜一区二区三区在线观看 | 日韩视频在线一区二区| 欧美精品电影在线| 中文欧美字幕免费| 亚洲午夜av| 美日韩精品免费观看视频| 欧美黄在线观看| 欧美啪啪一区| 亚洲免费影院| 欧美一区二区三区免费视| 久久久噜噜噜久久| 欧美久久久久免费| 中国成人亚色综合网站| 国产精品99久久久久久久久久久久 | 欧美国产日韩在线| 亚洲一区二区在线免费观看| 欧美有码在线观看视频| 亚洲精选91| 香蕉久久a毛片| aa级大片欧美三级| 久久精品国产亚洲aⅴ| 99国产精品久久久久久久成人热| 久久亚洲精品网站| 欧美99久久| 久久久久免费视频| 欧美激情视频在线播放| 欧美在线观看一区| 欧美日本国产视频| 久久婷婷蜜乳一本欲蜜臀| 亚洲在线国产日韩欧美| 在线观看欧美日本| 亚洲永久在线观看| 99精品国产福利在线观看免费| 麻豆freexxxx性91精品| 亚洲女同在线| 亚洲国产日韩在线| 久久免费的精品国产v∧| 欧美国产日韩一二三区| 亚洲午夜精品| 欧美大片91| 樱桃成人精品视频在线播放| 宅男噜噜噜66一区二区66| 亚洲午夜久久久久久尤物| 在线观看视频一区二区欧美日韩| 亚洲欧洲美洲综合色网| 欧美亚洲一区二区三区| 欧美一区亚洲一区| 99精品免费视频| 久久国产一区二区三区| 欧美亚洲自偷自偷| 欧美精品1区2区3区| 久久在线视频| 欧美午夜电影在线| 亚洲第一页在线| 国产伦精品一区二区三区视频黑人| 99在线观看免费视频精品观看| 欧美国产日韩xxxxx| 国产精品精品视频| 亚洲国产综合在线| 国内精品伊人久久久久av影院| 久久国产精品久久精品国产| 欧美大片在线观看| 午夜激情综合网| 欧美成熟视频| 亚洲国产小视频在线观看| 欧美日韩综合不卡| 欧美xart系列在线观看| 国产精品美女诱惑| 亚洲精品女av网站| 国产综合久久| 久久爱www| 欧美日韩国产一区二区三区| 99re6热在线精品视频播放速度| 美女精品在线观看| 久久精品国产亚洲一区二区三区| 在线播放日韩欧美| 亚洲高清在线观看一区| 国产尤物精品| 性xx色xx综合久久久xx| 亚洲综合国产| 欧美一区二区三区婷婷月色 | 久久久一本精品99久久精品66| 国产一区二区三区av电影| 亚洲乱码国产乱码精品精 | 亚洲欧美一区二区在线观看| 欧美成人精品一区二区三区| 久久久精品国产99久久精品芒果| 亚洲少妇自拍| 国产精品日韩精品| 欧美一区=区| 国产欧美精品久久| 欧美在线看片a免费观看| 欧美影院久久久| 国产亚洲毛片| 久久精品视频免费观看| 欧美第一黄网免费网站| 亚洲国产影院| 久久精品一区二区| 久久影视三级福利片| 亚洲国产视频a| 欧美裸体一区二区三区| 一本色道久久综合亚洲二区三区| 国产精品一区久久久| 亚洲另类在线一区| 久久久久久久久久久久久9999| 欧美大秀在线观看| 日韩网站在线| 欧美一级在线播放| 精品动漫一区二区| 国产精品五区| 老司机成人网| 久久国产精品毛片| 在线免费观看日本欧美| 欧美人与性动交a欧美精品| 久久精品一本久久99精品| 91久久精品久久国产性色也91| 国内成人精品视频| 一区二区久久久久| 久久久久网址| 亚洲国产另类久久久精品极度 | 日韩午夜在线播放| 亚洲破处大片| 国产精品久久久久久久久久尿|