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

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>
            亚洲欧美日韩国产一区| 中国成人在线视频| 欧美福利在线观看| 欧美福利影院| 欧美日韩色综合| 国产精品毛片大码女人| 国产精品乱码妇女bbbb| 国产免费观看久久| 国产在线精品一区二区中文| 国产自产高清不卡| 亚洲国产欧美在线人成| 日韩亚洲成人av在线| 亚洲在线电影| 久久精品欧美日韩| 欧美**人妖| 日韩视频免费观看高清完整版| 亚洲精品日韩欧美| 欧美影片第一页| 欧美久久久久久久久| 国产欧美日韩视频一区二区| 国产在线国偷精品产拍免费yy| 亚洲第一精品夜夜躁人人爽| 一区二区三区四区五区精品视频| 欧美亚洲三级| 亚洲第一久久影院| av成人免费在线| 欧美在线免费看| 欧美日韩一区二区三区| 国产亚洲精品v| 亚洲校园激情| 欧美激情小视频| 亚洲小说欧美另类婷婷| 免费观看日韩av| 国产精品揄拍500视频| 亚洲国内欧美| 久久裸体艺术| 亚洲与欧洲av电影| 欧美激情在线狂野欧美精品| 国产一区二区按摩在线观看| 亚洲一二三区精品| 亚洲高清在线| 久久久久久久一区二区三区| 国产精品久久久久久一区二区三区| 一区二区三区在线免费视频| 欧美一级播放| 999亚洲国产精| 欧美激情国产日韩| 亚洲激情社区| 嫩草国产精品入口| 性做久久久久久久免费看| 欧美区日韩区| 99国产精品自拍| 亚洲欧洲另类国产综合| 蜜臀av性久久久久蜜臀aⅴ| 亚洲深夜福利在线| 欧美成人免费播放| 性色一区二区| 国产欧美91| 久久精品系列| 久久精品国产77777蜜臀| 国产午夜精品理论片a级探花| 这里只有精品视频在线| 亚洲精品国产视频| 欧美精品在线观看播放| 亚洲国内欧美| 亚洲人成在线观看网站高清| 欧美成人中文字幕| 最新日韩中文字幕| 亚洲精品久久久一区二区三区| 欧美成人精品福利| 亚洲人精品午夜| 亚洲欧洲综合另类| 欧美日韩视频一区二区三区| 一本在线高清不卡dvd| 99视频在线精品国自产拍免费观看| 欧美日韩国产91| 亚洲欧美色一区| 欧美在线视频一区| 在线观看日韩av电影| 亚洲黄色大片| 欧美亚男人的天堂| 久久久久一区二区三区四区| 久久这里只有精品视频首页| 亚洲黄色三级| 一本色道久久综合狠狠躁篇怎么玩| 国产精品第一区| 久久久噜久噜久久综合| 久久久免费精品| 亚洲一区3d动漫同人无遮挡| 欧美一级日韩一级| 亚洲国产第一| 亚洲午夜日本在线观看| 国语自产偷拍精品视频偷| 女女同性女同一区二区三区91| 欧美激情国产日韩| 欧美在线观看视频一区二区| 久久久久久一区二区| 一区二区日韩免费看| 性欧美长视频| 日韩视频免费在线| 香蕉久久国产| 一区二区三区精密机械公司 | 久久成人精品无人区| 91久久在线| 欧美亚洲综合久久| 99成人精品| 久久蜜桃精品| 亚洲一二三区在线观看| 久久精品最新地址| 亚洲欧美日韩综合aⅴ视频| 猛男gaygay欧美视频| 欧美中文在线免费| 久久激情视频久久| 久久精品九九| 亚洲一区二区在线看| 久久米奇亚洲| 亚洲欧美日韩天堂一区二区| 免费视频一区| 另类成人小视频在线| 国产精品亚洲激情| 一卡二卡3卡四卡高清精品视频| 国精产品99永久一区一区| 亚洲精品永久免费| 亚洲理论在线| 免费看黄裸体一级大秀欧美| 美女诱惑黄网站一区| 国产午夜精品全部视频播放 | 一区二区三区视频观看| 久久久亚洲国产天美传媒修理工 | 欧美在线视屏| 欧美午夜精品伦理| 亚洲乱码国产乱码精品精天堂| 亚洲国产午夜| 毛片基地黄久久久久久天堂| 毛片一区二区| 在线观看亚洲精品| 久久野战av| 亚洲成在线观看| 伊人色综合久久天天| 久久久久国产精品一区| 麻豆精品视频在线| 亚洲国产精品专区久久| 久久精品亚洲一区二区三区浴池| 久久香蕉国产线看观看av| 国产综合久久| 久久亚洲一区二区三区四区| 亚洲电影第三页| 一区二区三区av| 国产精品嫩草99a| 午夜日韩av| 久久综合给合久久狠狠狠97色69| 精品1区2区| 免费国产自线拍一欧美视频| 欧美激情aⅴ一区二区三区| 亚洲国产精选| 欧美性大战久久久久久久| 午夜免费在线观看精品视频| 久久午夜电影网| 99精品视频一区| 国产精品一二三四| 久久一区精品| 日韩一二三区视频| 欧美一区二区三区四区夜夜大片| 国内精品久久久久久影视8 | 国产日韩欧美在线视频观看| 欧美一级免费视频| 欧美激情黄色片| 亚洲欧美日韩在线不卡| 激情丁香综合| 国产精品成人午夜| 久久久久久夜精品精品免费| 亚洲国产精品国自产拍av秋霞| 亚洲无线视频| 亚洲国产小视频| 国产精品一区二区在线观看不卡| 亚洲欧美资源在线| 欧美成人小视频| 亚洲免费视频一区二区| 欧美国产丝袜视频| 午夜精品三级视频福利| 亚洲第一精品影视| 国产精品欧美经典| 欧美福利视频| 久久大香伊蕉在人线观看热2| 亚洲区免费影片| 久久女同互慰一区二区三区| 一本色道综合亚洲| **欧美日韩vr在线| 国产精品视频xxx| 欧美理论在线播放| 老司机成人在线视频| 欧美一区二区三区免费观看 | 先锋影音国产一区| 日韩午夜在线电影| 亚洲高清免费视频| 久久尤物视频| 久久成人精品视频| 性欧美1819性猛交| 午夜精品亚洲| 亚洲一区二区三区四区五区黄|