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

隨筆 - 224  文章 - 41  trackbacks - 0
<2010年1月>
272829303112
3456789
10111213141516
17181920212223
24252627282930
31123456

享受編程

常用鏈接

留言簿(11)

隨筆分類(159)

隨筆檔案(224)

文章分類(2)

文章檔案(4)

經(jīng)典c++博客

搜索

  •  

最新評論

閱讀排行榜

評論排行榜

原文地址:http://www.cnblogs.com/Kevin-moon/archive/2009/01/13/1374353.html

 過年前的這段時(shí)間真是舒服,沒有了平時(shí)項(xiàng)目發(fā)版的緊張,剩下的就是只有在網(wǎng)上閑逛了,哈哈!
     今天早上閑逛的時(shí)候,在CodeProject發(fā)現(xiàn)了個(gè)不錯(cuò)的文章,英文好的直接去http://www.codeproject.com/KB/threads/SynchronizationContext.aspx看吧,不好,就將就的看下我的吧,呵呵!(沒有直接翻譯,不過大概的思路相同)

理解SynchronizationContext


  SynchronizationContext 類是一個(gè)基類,可提供不帶同步的自由線程上下文。 此類實(shí)現(xiàn)的同步模型的目的是使公共語言運(yùn)行庫內(nèi)部的異步/同步操作能夠針對不同的異步模型采取正確的行為。此模型還簡化了托管應(yīng)用程序?yàn)樵诓煌耐江h(huán)境下正常工作而必須遵循的一些要求。同步模型的提供程序可以擴(kuò)展此類并為這些方法提供自己的實(shí)現(xiàn)。(來自MSDN)
  簡而言之就是允許一個(gè)線程和另外一個(gè)線程進(jìn)行通訊,SynchronizationContext在通訊中充當(dāng)傳輸者的角色。另外這里有個(gè)地方需要清楚的,不是每個(gè)線程都附加SynchronizationContext這個(gè)對象,只有UI線程是一直擁有的。
  這里你可能有個(gè)問題:對于UI線程來說,是如何將SynchronizationContext這個(gè)對象附加到線程上的呢?!OK,我們先從下面的代碼開始,

 

[STAThread]
static void Main()
{
    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(
false);

    
// let's check the context here
    var context = SynchronizationContext.Current;
    
if (context == null)
        MessageBox.Show(
"No context for this thread");
    
else
        MessageBox.Show(
"We got a context");

    
// create a form
    Form1 form = new Form1();

    
// let's check it again after creating a form
    context = SynchronizationContext.Current;

    
if (context == null)
        MessageBox.Show(
"No context for this thread");
    
else
        MessageBox.Show(
"We got a context");

    
if (context == null)
        MessageBox.Show(
"No context for this thread");

    Application.Run(
new Form1());
}

運(yùn)行結(jié)果:
1、No context for this thread
2、We got a context

     
     從運(yùn)行結(jié)果來看,在Form1 form = new Form1()之前,SynchronizationContext對象是為空,而當(dāng)實(shí)例化Form1窗體后,SynchronizationContext對象就被附加到這個(gè)線程上了。所以可以得出答案了:當(dāng)Control對象被創(chuàng)建的同時(shí),SynchronizationContext對象也會被創(chuàng)建并附加到線程上。
     好的,我們既然已經(jīng)基本了解了SynchronizationContext,接下來的事情就是使用它了!

如何使用SynchronizationContext


  應(yīng)用程序有兩個(gè)線程:線程A和線程B,不過線程B比較特殊,它屬于UI線程,當(dāng)這兩個(gè)線程同時(shí)運(yùn)行的時(shí)候,線程A有個(gè)需求:"修改UI對象的屬性",這時(shí)候如果你是線程A,你會如何去完成需求呢?!

第一種方式:
     
     在線程A上面直接去操作UI對象,這是線程B說:"線程A,你真xx,你不知道我的特殊嘛!",然后直接拋給線程A一個(gè)異常信息,線程A得到異常后,一臉的無辜和無奈.....!

第二種方式:
  InvokeRequired?!是的,當(dāng)然沒問題。(解釋下,InvokeRequired屬性是每個(gè)Control對象都具有的屬性,它會返回true和false,當(dāng)是true的時(shí)候,表示它在另外一個(gè)線程上面,這是必須通過Invoke,BeginInvoke這些方法來調(diào)用更新UI對象的方法,當(dāng)是false的時(shí)候,有兩種情況,1:位于當(dāng)前線程上面,可以通過直接去調(diào)用修改UI對象的方法,2:位于不同的線程上,不過控件或窗體的句柄不存在。對于句柄是否存在的判斷,可以通過IsHandleCreated來獲取,如果句柄不存在,是不能調(diào)用Invoke...這些方法的,這時(shí)候你必須等待句柄的創(chuàng)建
通過InvokeRequired的實(shí)現(xiàn)方式如下:
using System;
using System.Drawing;
using System.Windows.Forms;
using System.Threading;

   
public class MyFormControl : Form
   {
      
public delegate void AddListItem(String myString);
      
public AddListItem myDelegate;
      
private Button myButton;
      
private Thread myThread;
      
private ListBox myListBox;
      
public MyFormControl()
      {
         myButton 
= new Button();
         myListBox 
= new ListBox();
         myButton.Location 
= new Point(72160);
         myButton.Size 
= new Size(15232);
         myButton.TabIndex 
= 1;
         myButton.Text 
= "Add items in list box";
         myButton.Click 
+= new EventHandler(Button_Click);
         myListBox.Location 
= new Point(4832);
         myListBox.Name 
= "myListBox";
         myListBox.Size 
= new Size(20095);
         myListBox.TabIndex 
= 2;
         ClientSize 
= new Size(292273);
         Controls.AddRange(
new Control[] {myListBox,myButton});
         Text 
= " 'Control_Invoke' example ";
         myDelegate 
= new AddListItem(AddListItemMethod);
      }
      
static void Main()
      {
         MyFormControl myForm 
= new MyFormControl();
         myForm.ShowDialog();
      }
      
public void AddListItemMethod(String myString)
      {
            myListBox.Items.Add(myString);
      }
      
private void Button_Click(object sender, EventArgs e)
      {
         myThread 
= new Thread(new ThreadStart(ThreadFunction));
         myThread.Start();
      }
      
private void ThreadFunction()
      {
         MyThreadClass myThreadClassObject  
= new MyThreadClass(this);
         myThreadClassObject.Run();
      }
   }
   
public class MyThreadClass
   {
      MyFormControl myFormControl1;
      
public MyThreadClass(MyFormControl myForm)
      {
         myFormControl1 
= myForm;
      }
      String myString;

      
public void Run()
      {
         
for (int i = 1; i <= 5; i++)
         {
            myString 
= "Step number " + i.ToString() + " executed";
            Thread.Sleep(
400);
            
// Execute the specified delegate on the thread that owns
            
// 'myFormControl1' control's underlying window handle with
            
// the specified list of arguments.
            myFormControl1.Invoke(myFormControl1.myDelegate,
                                   
new Object[] {myString});
         }
      }
   }

    不過這里存在一個(gè)有爭論的地方:這種方式必須通過調(diào)用Control的Invoke方法來實(shí)現(xiàn),這就是說調(diào)用的地方必須有一個(gè)Control的引用存在。
  看下MyThreadClass類,這個(gè)類中就存在MyFormControl的引用對象。其實(shí)如果這個(gè)類放在這里是沒有任務(wù)不妥之處的,但是如果把MyThreadClass類放在業(yè)務(wù)層,這時(shí)候問題就出現(xiàn)了,從設(shè)計(jì)角度來說,業(yè)務(wù)層是不允許和UI有任何關(guān)系,所以MyFormControl的引用對象絕對不能存在于MyThreadClass類,但是不讓它存在,更新UI控件的需求就滿足不了,這種情況下,我們?nèi)绾巫龅揭环N最佳方案呢???

第三種方式:
  本文的主角:SynchronizationContext登場了。解釋之前,先讓下面的代碼做下鋪墊,
public partial class Form1 : Form
{
    
public Form1()
    {
        InitializeComponent();
    }

    
private void mToolStripButtonThreads_Click(object sender, EventArgs e)
    {
        
// let's see the thread id
        int id = Thread.CurrentThread.ManagedThreadId;
        Trace.WriteLine(
"mToolStripButtonThreads_Click thread: " + id);

        
// grab the sync context associated to this
        
// thread (the UI thread), and save it in uiContext
        
// note that this context is set by the UI thread
        
// during Form creation (outside of your control)
        
// also note, that not every thread has a sync context attached to it.
        SynchronizationContext uiContext = SynchronizationContext.Current;

        
// create a thread and associate it to the run method
        Thread thread = new Thread(Run);

        
// start the thread, and pass it the UI context,
        
// so this thread will be able to update the UI
        
// from within the thread
        thread.Start(uiContext);
    }

    
private void Run(object state)
    {
        
// lets see the thread id
        int id = Thread.CurrentThread.ManagedThreadId;
        Trace.WriteLine(
"Run thread: " + id);

        
// grab the context from the state
        SynchronizationContext uiContext = state as SynchronizationContext;

        
for (int i = 0; i < 1000; i++)
        {
            
// normally you would do some code here
            
// to grab items from the database. or some long
            
// computation
            Thread.Sleep(10);

            
// use the ui context to execute the UpdateUI method,
            
// this insure that the UpdateUI method will run on the UI thread.

            uiContext.Post(UpdateUI, 
"line " + i.ToString());
        }
    }

    
/// <summary>
    
/// This method is executed on the main UI thread.
    
/// </summary>
    private void UpdateUI(object state)
    {
        
int id = Thread.CurrentThread.ManagedThreadId;
        Trace.WriteLine(
"UpdateUI thread:" + id);
        
string text = state as string;
        mListBox.Items.Add(text);
    }
}

運(yùn)行結(jié)果:

mToolStripButtonThreads_Click thread: 10
Run thread: 
3
UpdateUI thread:
10
UpdateUI thread:
10
UpdateUI thread:
10
UpdateUI thread:
10
 (x1000 times)

    程序首先在Form1窗體的mToolStripButtonThreads_Click事件中,獲取當(dāng)前的SynchronizationContext對象,然后啟動另外一個(gè)線程,并且將SynchronizationContext對象傳遞給啟動的線程,啟動的線程通過SynchronizationContext對象的Post方法來調(diào)用一個(gè)委托方法UpdateUI,因?yàn)閁pdateUI是執(zhí)行在主UI線程上的,所以可以通過它來修改UI上對象的信息。
    怎么樣!不錯(cuò)吧,現(xiàn)在我們可以把Control引用給拋棄了,哈哈!
    如果你去查下MSDN,會發(fā)現(xiàn)SynchronizationContext還有一個(gè)Send方法,Send和Post有什么區(qū)別?

Send VS Post,以及異常處理


首先看下異常處理的情況
private void Run(object state)
{
    
// let's see the thread id
    int id = Thread.CurrentThread.ManagedThreadId;
    Trace.WriteLine(
"Run thread: " + id);

    
// grab the context from the state
    SynchronizationContext uiContext = state as SynchronizationContext;

    
for (int i = 0; i < 1000; i++)
    {
        Trace.WriteLine(
"Loop " + i.ToString());
        
// normally you would do some code here
        
// to grab items from the database. or some long
        
// computation
        Thread.Sleep(10);

        
// use the ui context to execute the UpdateUI method, this insure that the
        
// UpdateUI method will run on the UI thread.

        
try
        {
            uiContext.Send(UpdateUI, 
"line " + i.ToString());
        }
        
catch (Exception e)
        {
            Trace.WriteLine(e.Message);
        }
    }
}

/// <summary>
/// This method is executed on the main UI thread.
/// </summary>
private void UpdateUI(object state)
{
    
throw new Exception("Boom");
}

   當(dāng)你運(yùn)行的時(shí)候, 你可能希望在UI線程上面去拋出,但是結(jié)果往往出忽你的意料,異常信息都在Run方法的線程上被捕獲了。這時(shí)候你可能想問:WHY?!
   解釋之前,我們先看下,Send VS Post的結(jié)果:
   Send 方法啟動一個(gè)同步請求以發(fā)送消息
   Post 方法啟動一個(gè)異步請求以發(fā)送消息。    
   哈哈,異常處理的答案迎韌而解了吧!

    今天就寫到這里吧,下一篇和大家討論下SynchronizationContext是否在所有線程中都適用...

 

posted on 2010-09-07 12:10 漂漂 閱讀(989) 評論(1)  編輯 收藏 引用 所屬分類: c#開發(fā)

FeedBack:
# re: 線程之間的通訊 UI 通訊 SynchronizationContext 使用 2010-12-28 15:03 lxf
uiContext.Send(UpdateUI, "line " + i.ToString());
參數(shù)不行吧??  回復(fù)  更多評論
  
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
              日韩一区二区电影网| 乱码第一页成人| 欧美成人视屏| 久久久女女女女999久久| 久久国产婷婷国产香蕉| 欧美在线视频播放| 久久久国产成人精品| 模特精品在线| 亚洲精品专区| 亚洲欧美日韩国产精品| 久久精品一区四区| 欧美成人亚洲成人日韩成人| 欧美精品一区二区三区四区| 欧美日韩在线影院| 国产日韩欧美中文在线播放| 亚洲成在人线av| 一本色道久久综合亚洲精品不| 亚洲一区制服诱惑| 久久久精品一区| 亚洲精品一区二区三区四区高清| 亚洲天堂av在线免费| 久久精品中文字幕一区二区三区| 美女视频黄免费的久久| 国产精品欧美久久| 亚洲欧洲日本国产| 午夜精品久久久久影视 | 亚洲韩国青草视频| 99www免费人成精品| 欧美在线观看网址综合| 欧美精品免费在线观看| 狠狠做深爱婷婷久久综合一区| 日韩亚洲精品视频| 久久综合给合| 亚洲欧美久久| 欧美色一级片| 亚洲精品综合| 麻豆成人小视频| 亚洲黄色免费| 又紧又大又爽精品一区二区| 一本色道久久88综合亚洲精品ⅰ| 久久精品国产免费| 亚洲欧美精品在线| 国产精品成人国产乱一区| 亚洲国产aⅴ天堂久久| 美女诱惑一区| 欧美伦理在线观看| 亚洲图片欧美日产| 亚洲欧美在线aaa| 国产精品夜夜夜| 另类成人小视频在线| 免费日韩成人| 亚洲午夜精品| 久久亚洲精品一区二区| 亚洲靠逼com| 亚洲欧美日韩国产综合在线| 一区久久精品| 一区二区三区精品久久久| 国产午夜精品久久久久久免费视| 欧美在线视频免费| 欧美第十八页| 久久偷窥视频| 国产精品伦子伦免费视频| 麻豆精品一区二区综合av| 国产精品igao视频网网址不卡日韩| 久久精品国产亚洲5555| 欧美日韩成人精品| 免费在线播放第一区高清av| 欧美日韩亚洲一区二区三区四区 | 亚洲欧美在线磁力| 亚洲毛片一区二区| 久久夜色精品国产亚洲aⅴ| 欧美激情 亚洲a∨综合| 国产精品一级在线| 亚洲午夜国产成人av电影男同| 136国产福利精品导航网址| 欧美在线视屏| 久久久久中文| 亚洲成色www久久网站| 久久久久免费| 欧美成人午夜激情视频| 亚洲风情亚aⅴ在线发布| 欧美电影免费观看大全| 免费成人毛片| 一区二区三区|亚洲午夜| 欧美日韩在线免费视频| 亚洲一二区在线| 欧美 日韩 国产 一区| 亚洲国产裸拍裸体视频在线观看乱了| 久久久人成影片一区二区三区观看 | 午夜精品久久久99热福利| 欧美一区国产二区| 在线精品亚洲一区二区| 欧美日韩大片| 久久不见久久见免费视频1| 免费亚洲一区二区| 亚洲狼人精品一区二区三区| 国产精品wwwwww| 久久久久久**毛片大全| 99综合电影在线视频| 欧美va亚洲va国产综合| 亚洲欧美日韩在线一区| 狠狠久久婷婷| 国产精品久久久久久亚洲调教| 亚洲免费影院| 亚洲精品乱码久久久久久| 国产专区欧美精品| 国产精品日韩欧美大师| 欧美日韩视频一区二区| 久久久久久久久久久久久女国产乱| av不卡免费看| 亚洲乱码精品一二三四区日韩在线| 久久手机免费观看| 久久精品夜夜夜夜久久| 久久福利影视| 久久久久久久久岛国免费| 午夜精品久久久久久久久久久| 一区二区三区黄色| 亚洲一区三区在线观看| 亚洲婷婷综合色高清在线| 一区二区三区四区蜜桃| 99精品免费视频| 亚洲小说欧美另类社区| 亚洲视频电影图片偷拍一区| 亚洲欧美国产日韩中文字幕| 亚洲综合导航| 免费欧美电影| 日韩亚洲欧美在线观看| 中文精品视频一区二区在线观看| 一区二区三区欧美在线| 亚洲欧美日韩在线观看a三区 | 亚洲资源在线观看| 久久亚洲一区| 亚洲免费成人| 久久久久综合| 国产精品捆绑调教| 在线播放国产一区中文字幕剧情欧美| 在线观看中文字幕亚洲| 亚洲在线中文字幕| 欧美国产欧美亚州国产日韩mv天天看完整| 欧美成ee人免费视频| 亚洲专区免费| 欧美人与性动交cc0o| 激情国产一区二区| 欧美一级视频一区二区| 狠狠色狠狠色综合日日小说| 一本色道久久综合亚洲91| 久久天堂成人| 香蕉久久久久久久av网站| 欧美午夜电影在线| 中文精品99久久国产香蕉| 亚洲激情综合| 美女91精品| 91久久久精品| 亚洲国产天堂网精品网站| 久久一区欧美| 亚洲福利电影| 亚洲日本久久| 国产精品电影观看| 小黄鸭精品aⅴ导航网站入口| 一区二区三区四区国产| 国产精品视频免费在线观看| 性色av一区二区三区| 亚洲免费视频一区二区| 国产精品一区二区黑丝| 久久久国产精彩视频美女艺术照福利| 亚洲专区免费| 精品成人在线视频| 亚洲国产婷婷| 国产精品一区二区男女羞羞无遮挡| 亚洲网站在线看| 欧美在线免费视屏| 亚洲精品国产无天堂网2021| 一本色道久久99精品综合| 国产一区二区日韩| 亚洲乱码国产乱码精品精| 好看不卡的中文字幕| 亚洲精品专区| 在线看无码的免费网站| 亚洲永久免费av| 一区二区不卡在线视频 午夜欧美不卡在 | 久久精品国产99国产精品澳门| 亚洲高清资源| 久久成人精品电影| 亚洲欧美日韩一区二区三区在线观看 | 亚洲自拍啪啪| 欧美精品久久久久久久久久| 久久资源在线| 一区二区三区自拍| 久久国产精品第一页| 欧美中日韩免费视频| 欧美视频在线观看一区| 亚洲国产婷婷香蕉久久久久久| 国产日韩在线看片| 欧美一级理论性理论a| 欧美专区中文字幕| 国产日韩av在线播放| 欧美在线免费观看| 美女黄网久久| 99一区二区| 国产精品一区二区久久精品|