• <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>

            道。道。道

            安全特性不等于安全的特性

               :: 首頁 :: 聯(lián)系 :: 聚合  :: 管理

            常用鏈接

            搜索

            •  

            最新評論

            問題的產(chǎn)生:

              我的WinForm程序中有一個用于更新主窗口的工作線程(worker thread),但文檔中卻提示我不能在多線程中調(diào)用這個form(為什么?),而事實上我在調(diào)用時程序常常會崩掉。請問如何從多線程中調(diào)用form中的方法呢?

              解答:

              每一個從Control類中派生出來的WinForm類(包括Control類)都是依靠底層Windows消息和一個消息泵循環(huán)(message pump loop)來執(zhí)行的。消息循環(huán)都必須有一個相對應(yīng)的線程,因為發(fā)送到一個window的消息實際上只會被發(fā)送到創(chuàng)建該window的線程中去。其結(jié)果是,即使提供了同步(synchronization),你也無法從多線程中調(diào)用這些處理消息的方法。大多數(shù)plumbing是掩藏起來的,因為WinForm是用代理(delegate)將消息綁定到事件處理方法中的。WinForm將Windows消息轉(zhuǎn)換為一個基于代理的事件,但你還是必須注意,由于最初消息循環(huán)的緣故,只有創(chuàng)建該form的線程才能調(diào)用其事件處理方法。如果你在你自己的線程中調(diào)用這些方法,則它們會在該線程中處理事件,而不是在指定的線程中進(jìn)行處理。你可以從任何線程中調(diào)用任何不屬于消息處理的方法。

              Control類(及其派生類)實現(xiàn)了一個定義在System.ComponentModel命名空間下的接口 -- ISynchronizeInvoke,并以此來處理多線程中調(diào)用消息處理方法的問題:

            public interface ISynchronizeInvoke
            {
             object Invoke(Delegate method,object[] args);
             IAsyncResult BeginInvoke(Delegate method,object[] args);
             object EndInvoke(IAsyncResult result);
             bool InvokeRequired {get;}
            }

              ISynchronizeInvoke提供了一個普通的標(biāo)準(zhǔn)機(jī)制用于在其他線程的對象中進(jìn)行方法調(diào)用。例如,如果一個對象實現(xiàn)了ISynchronizeInvoke,那么在線程T1上的客戶端可以在該對象中調(diào)用ISynchronizeInvoke的Invoke()方法。Invoke()方法的實現(xiàn)會阻塞(block)該線程的調(diào)用,它將調(diào)用打包發(fā)送(marshal)到 T2,并在T2中執(zhí)行調(diào)用,再將返回值發(fā)送會T1,然后返回到T1的客戶端。Invoke()方法以一個代理來定位該方法在T2中的調(diào)用,并以一個普通的對象數(shù)組做為其參數(shù)。

              調(diào)用者還可以檢查InvokeRequired屬性,因為你既可以在同一線程中調(diào)用ISynchronizeInvoke也可以將它重新定位(redirect)到其他線程中去。如果InvokeRequired的返回值是false的話,則調(diào)用者可以直接調(diào)用該對象的方法。

              比如,假設(shè)你想要從另一個線程中調(diào)用某個form中的Close方法,那么你可以使用預(yù)先定義好的的MethodInvoker代理,并調(diào)用Invoke方法:

            Form form;
            /* obtain a reference to the form,
            then: */
            ISynchronizeInvoke synchronizer;
            synchronizer = form;

            if(synchronizer.InvokeRequired)
            {
            MethodInvoker invoker = new
            MethodInvoker(form.Close);
            synchronizer.Invoke(invoker,null);
            }
            else
            form.Close();

              ISynchronizeInvoke不僅僅用于WinForm中。例如,一個Calculator類提供了將兩個數(shù)字相加的Add()方法,它就是通過ISynchronizeInvoke來實現(xiàn)的。用戶必須確定ISynchronizeInvoke.Invoke()方法的調(diào)用是執(zhí)行在正確的線程中的。

              C# 在正確的線程中寫入調(diào)用

              列表A. Calculator類的Add()方法用于將兩個數(shù)字相加。如果用戶直接調(diào)用Add()方法,它會在該用戶的線程中執(zhí)行調(diào)用,而用戶可以通過ISynchronizeInvoke.Invoke()將調(diào)用寫入正確的線程中。

              列表A:

            public class Calculator : ISynchronizeInvoke
            {
             public int Add(int arg1,int arg2)
             { 
              int threadID = Thread.CurrentThread.GetHashCode();
              Trace.WriteLine( "Calculator thread ID is " + threadID.ToString());
              return arg1 + arg2;
             }
             //ISynchronizeInvoke implementation
             public object Invoke(Delegate method,object[] args)
             {
              public IAsyncResult BeginInvoke(Delegate method,object[] args)
              {
               public object EndInvoke(IAsyncResult result)
               {
                public bool InvokeRequired
                {
                }
               }
               //Client-side code
               public delegate int AddDelegate(int arg1,int arg2);

                int threadID = Thread.CurrentThread.GetHashCode();
                Trace.WriteLine("Client thread ID is " + threadID.ToString());

                Calculator calc;
                /* Some code to initialize calc */

                AddDelegate addDelegate = new AddDelegate(calc.Add);

                object[] arr = new object[2];
                arr[0] = 3;
                arr[1] = 4;

                int sum = 0;
                sum = (int) calc.Invoke(addDelegate,arr);
                Debug.Assert(sum ==7);

                /* Possible output:
                Calculator thread ID is 29
                Client thread ID is 30
                */

              或許你并不想進(jìn)行同步調(diào)用,因為它被打包發(fā)送到另一個線程中去了。你可以通過BeginInvoke()和EndInvoke()方法來實現(xiàn)它。你可以依照通用的.NET非同步編程模式(asynchronous programming model)來使用這些方法:用BeginInvoke()來發(fā)送調(diào)用,用EndInvoke()來實現(xiàn)等待或用于在完成時進(jìn)行提示以及收集返回結(jié)果。

              還值得一提的是ISynchronizeInvoke方法并非安全類型。 類型不符會導(dǎo)致在執(zhí)行時被拋出異常,而不是編譯錯誤。所以在使用ISynchronizeInvoke時要格外注意,因為編輯器無法檢查出執(zhí)行錯誤。

              實現(xiàn)ISynchronizeInvoke要求你使用一個代理來在后期綁定(late binding)中動態(tài)地調(diào)用方法。每一種代理類型均提供DynamicInvoke()方法: public object DynamicInvoke(object[]
            args);

              理論上來說,你必須將一個方法代理放到一個需要提供對象運行的真實的線程中去,并使Invoke() 和BeginInvoke()方法中的代理中調(diào)用DynamicInvoke()方法。ISynchronizeInvoke的實現(xiàn)是一個非同一般的編程技巧,本文附帶的源文件中包含了一個名為Synchronizer的幫助類(helper class)和一個測試程序,這個測試程序是用來論證列表A中的Calculator類是如何用Synchronizer類來實現(xiàn)ISynchronizeInvoke的。Synchronizer是ISynchronizeInvoke的一個普通實現(xiàn),你可以使用它的派生類或者將其本身作為一個對象來使用,并將ISynchronizeInvoke實現(xiàn)指派給它。

              用來實現(xiàn)Synchronizer的一個重要元素是使用一個名為WorkerThread的嵌套類(nested class)。WorkerThread中有一個工作項目(work item)查詢。WorkItem類中包含方法代理和參數(shù)。Invoke()和BeginInvoke()用來將一個工作項目實例加入到查詢里。WorkerThread新建一個.NET worker線程,它負(fù)責(zé)監(jiān)測工作項目的查詢?nèi)蝿?wù)。查詢到項目之后,worker會讀取它們,然后調(diào)用DynamicInvoke()方法。

            posted on 2007-10-15 12:08 獨孤九劍 閱讀(203) 評論(0)  編輯 收藏 引用 所屬分類: Learn articles
            久久久久亚洲精品无码蜜桃| 久久AV无码精品人妻糸列| 久久福利青草精品资源站免费 | 狠狠色丁香久久婷婷综合五月| 伊人久久大香线蕉综合影院首页| 91精品国产9l久久久久| 久久久免费观成人影院 | 99久久做夜夜爱天天做精品| 香港aa三级久久三级老师2021国产三级精品三级在 | 奇米影视7777久久精品人人爽 | 国产精品成人精品久久久| 亚洲国产精品成人AV无码久久综合影院| 亚洲精品成人网久久久久久| 精品久久8x国产免费观看| 狠狠色丁香久久婷婷综合_中| 国产精品99久久久久久人| 久久亚洲AV成人无码| 91亚洲国产成人久久精品| 久久亚洲AV成人无码国产| 人妻无码精品久久亚瑟影视| 久久黄色视频| 曰曰摸天天摸人人看久久久| 久久亚洲私人国产精品| 三级三级久久三级久久| 久久久久国产日韩精品网站| 久久综合狠狠色综合伊人| 久久国产精品成人影院| 无码超乳爆乳中文字幕久久| 久久无码AV中文出轨人妻| 欧美一级久久久久久久大片| 久久99精品久久久久久野外| 婷婷久久综合九色综合98| 99久久成人国产精品免费| 国产Av激情久久无码天堂| 久久精品国产精品亚洲毛片| 蜜臀av性久久久久蜜臀aⅴ| 久久亚洲AV成人无码电影| 色欲久久久天天天综合网 | 国产精品久久久久久久久软件| 久久精品成人免费观看97| 久久婷婷五月综合色99啪ak |