亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > C# > 正文

深入理解C#中常見的委托

2020-01-24 03:13:34
字體:
來源:轉載
供稿:網友

一提到委托,浮現在我們腦海中的大概是聽的最多的就是類似C++的函數指針吧,呵呵,至少我的第一個反應是這樣的。
關于委托的定義和使用,已經有諸多的人講解過,并且講解細致入微。我就不用多廢話了。
今天我要說的是C#中的三種委托方式:Func委托Action委托,Predicate委托以及這三種委托的常見使用場景。
Func,Action,Predicate全面解析
首先來說明Func委托,通過MSDN我們可以了解到,Func委托有如下的5種類型:

復制代碼 代碼如下:

(1) *delegate TResult Func<TResult>();
(2)*delegate TResult Func<T1,TResult>(T1 arg1);
(3) *delegate TResult Func<T1,T2,TResult>(T1 arg1, T2 arg2);
(4)*delegate TResult Func<T1,T2,T3,TResult>(T1 arg1, T2 arg2, T3 arg3);
(5)*delegate TResult Func<T1,T2,T3,T4,TResult>T1 arg1, T2 arg2, T3 arg3, T4 arg4);

其中(1)只能委托無參但是有返回值的函數,TResult就是其返回類型。
而(2)只能委托具有一個傳入參數,有返回值的函數,T1為一個傳入參數,TResult為返回類型。
(3)只能委托具有二個傳入參數,有返回值的函數,T1和T2為兩個傳入參數,TResult為返回類型,(4)和(5)以此類推。
那么如何來使用呢? 下面給出一個簡單的幾個例子:
復制代碼 代碼如下:

#region Func委托

///Func<TResult>的用法
///這里TResult代表函數的返回值類型
///只能代理返回值為TResult類型的無參函數
Func<string> func = delegate()
{
    return "我是Func<TResult>委托出來的結果";
};
Console.WriteLine(func());
Console.ReadKey();
///Func<T,TResult>的用法
///這里的T為代理的函數的傳入類型,TResult代表函數的返回值類型
///只能代理參數為T類型,返回值為TResult類型的函數
Func<string, string> funcOne = delegate(string s)
{
    return s.ToUpper();
};
Console.WriteLine(funcOne("我是Func<T,TResult>委托出來的結果"));
Console.ReadKey();
///Func<T1,T2,TResult>的用法
///這里T1,T2為代理的函數的傳入類型,TResult代表函數的返回值類型
///只能代理參數為T1,T2類型,返回值為TResult類型的函數
Func<string, string, string> funcTwo = delegate(string value1, string value2)
{
    return value1 + " " + value2;
};
Console.WriteLine(funcTwo("我是", "Func<T1,T2,TResult>委托出來的結果"));
Console.ReadKey();
#endregion


上面代碼中,我用了匿名方法來代替函數,其中delegate()代表無參函數,delegate(string s)代表有一個傳入參數的函數,以下的以此類推。

然后需要說明的就是Action委托,這個委托也是非常常用的,尤其是在涉及到線程和界面交互的時候,配合著lamada表達式使用,非常方便的實現二者的交互。后面我會提到用法。
來看看Action委托的幾種表現形式:
復制代碼 代碼如下:

(1) * delegate void Action(); 無參,無返回值
(2)* delegate void Action<T>(T1 arg1);
(3)* delegate void Action<T1,T2>(T1 arg1, T2 arg2);
(4)* delegate void Action<T1,T2,T3>T1 arg1, T2 arg2, T3 arg3);
(5)* delegate void Action<T1,T2,T3,T4>T1 arg1, T2 arg2, T3 arg3, T4 arg4);

從上面可以看出,總共有5中表現形式,其中(1)既沒有傳入參數,也沒有返回值,那么它適合代理那些無參,無返回值的函數;(2)有一個傳入參數,無返回值,適合代理有參,無返回值的函數,(3)(4)(5)以此類推。最都容納四個傳入參數。
那么如何使用呢?下面有一些簡單的例子:
復制代碼 代碼如下:

#region Action的用法
///Action<T>的用法
///這里的T為代理函數的傳入類型,無返回值
Action<string[]> action = delegate(string[] x)
{
    var result = from p in x
     where p.Contains("s")
     select p;
    foreach (string s in result.ToList())
    {
        Console.WriteLine(s);
    }
};
string[] str={ "charlies","nancy","alex","jimmy","selina"};
action(str);
Console.ReadKey();
#endregion

上面的例子是通過傳入的String類型的數組,找出其中包含有字符s的項,然后輸出到控制臺。
最后一個就是Predicate委托,這個的形式比較少一些,就是一個傳入參數,返回值為bool類型,具體示例如下:
復制代碼 代碼如下:

#region Predicate
          ///bool Predicate<T>的用法
///輸入一個T類型的參數,返回值為bool類型
Predicate<string[]> predicate = delegate(string[] x)
{
    var result = from p in x
     where p.Contains("s")
     select p;
    if (result.ToList().Count > 0)
    {
        return true;
    }
    else
    {
        return false;
    }
};
string[] _value = { "charlies", "nancy", "alex", "jimmy", "selina" };
if (predicate(_value))
{
    Console.WriteLine("They contain.");
}
else
{
    Console.WriteLine("They don't contain.");
}
Console.ReadKey();
#endregion

上面的代碼其實也是判斷String數組中有沒有包含s的項,有的話就在控制臺打印出  They contain.沒有的話就打印出They don't contain.
總結一下這三個的特點就是:
復制代碼 代碼如下:

Func可以接受0個至4個傳入參數,必須具有返回值
Action可以接受0個至4個傳入參數,無返回值
Predicate只能接受一個傳入參數,返回值為bool類型

下面附上全部實現代碼:
復制代碼 代碼如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace DelegateIntegrateConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
#region Func委托

///Func<TResult>的用法
///這里TResult代表函數的返回值類型
///只能代理返回值為TResult類型的無參函數
Func<string> func = delegate()
{
    return "我是Func<TResult>委托出來的結果";
};
Console.WriteLine(func());
Console.ReadKey();
///Func<T,TResult>的用法
///這里的T為代理的函數的傳入類型,TResult代表函數的返回值類型
///只能代理參數為T類型,返回值為TResult類型的函數
Func<string, string> funcOne = delegate(string s)
{
    return s.ToUpper();
};
Console.WriteLine(funcOne("我是Func<T,TResult>委托出來的結果"));
Console.ReadKey();
///Func<T1,T2,TResult>的用法
///這里T1,T2為代理的函數的傳入類型,TResult代表函數的返回值類型
///只能代理參數為T1,T2類型,返回值為TResult類型的函數
Func<string, string, string> funcTwo = delegate(string value1, string value2)
{
    return value1 + " " + value2;
};
Console.WriteLine(funcTwo("我是", "Func<T1,T2,TResult>委托出來的結果"));
Console.ReadKey();
/*************余下的類似上面的這種操作,最多可以接受四個傳入參數***************
 *delegate TResult Func<TResult>(); 
 *delegate TResult Func<T1,TResult>(T1 arg1);
 *delegate TResult Func<T1,T2,TResult>(T1 arg1, T2 arg2);
 *delegate TResult Func<T1,T2,T3,TResult>(T1 arg1, T2 arg2, T3 arg3);
 *delegate TResult Func<T1,T2,T3,T4,TResult>T1 arg1, T2 arg2, T3 arg3, T4 arg4);
 */
#endregion
#region Action的用法
///Action<T>的用法
///這里的T為代理函數的傳入類型,無返回值
Action<string[]> action = delegate(string[] x)
{
    var result = from p in x
     where p.Contains("s")
     select p;
    foreach (string s in result.ToList())
    {
        Console.WriteLine(s);
    }
};
string[] str={ "charlies","nancy","alex","jimmy","selina"};
action(str);
Console.ReadKey();
/***************余下的類似上面的這種操作,最多可以接受四個傳入參數**********
 * delegate void Action(); 無參,無返回值
 * delegate void Action<T>(T1 arg1);
 * delegate void Action<T1,T2>(T1 arg1, T2 arg2);
 * delegate void Action<T1,T2,T3>T1 arg1, T2 arg2, T3 arg3);
 * delegate void Action<T1,T2,T3,T4>T1 arg1, T2 arg2, T3 arg3, T4 arg4);
 */
#endregion
#region Predicate
///bool Predicate<T>的用法
///輸入一個T類型的參數,返回值為bool類型
Predicate<string[]> predicate = delegate(string[] x)
{
    var result = from p in x
     where p.Contains("s")
     select p;
    if (result.ToList().Count > 0)
    {
        return true;
    }
    else
    {
        return false;
    }
};
string[] _value = { "charlies", "nancy", "alex", "jimmy", "selina" };
if (predicate(_value))
{
    Console.WriteLine("They contain.");
}
else
{
    Console.WriteLine("They don't contain.");
}
Console.ReadKey();
#endregion
        }
    }
}


下面這部分主要講解如何在WinForm中利用這些委托進行線程和界面的交互。
首先對于Func來說,由于其必須具有返回值,所以我們可以利用如下代碼來實現線程和界面的交互:
復制代碼 代碼如下:

#region 利用Func實現線程和界面交互
        private void AlternationUsingFunc(object text)
        {
//無參數,但是返回值為bool類型
this.Invoke(new Func<bool>(delegate()
{
    button1.Text = text.ToString();
    return true; //返回值
}));
        }
        private void AlternationUsingFuncThread()
        {
WaitCallback waitCallBack = new WaitCallback(this.AlternationUsingFunc);
ThreadPool.QueueUserWorkItem(waitCallBack, "Func的使用");
        }
        private void button1_Click(object sender, EventArgs e)
        {
AlternationUsingFuncThread();
        }
        #endregion

其中
復制代碼 代碼如下:

this.Invoke(new Func<bool>(delegate()
{
    button1.Text = text.ToString();
    return true; //返回值
}));

這段代碼中利用了Func<TResult>這種類型,也就是沒有傳入參數,但是有一個bool類型的返回值,然后將這個函數利用加入到線程池中,最后運行,這里我們成功的設置了button1的text為“Func的使用”。
然后,對于Action來說,由于其可以無參,無返回值,那么它的交互方式最為簡便,同時也是使用最多的,先看有參的調用方式:
復制代碼 代碼如下:

#region 利用Action實現線程和界面交互
        private void AlternationUsingAction(object text)
        {
//需要一個T類型的參數,無返回值
this.Invoke(new Action<object>(delegate(object myText)
{
    myText = text;
    button2.Text = text.ToString();
}),text);
        }
        private void AlternationUsingActionThread()
        {
WaitCallback waitCallBack = new WaitCallback(this.AlternationUsingAction);
ThreadPool.QueueUserWorkItem(waitCallBack,"Action的使用");
        }
        private void button2_Click(object sender, EventArgs e)
        {
AlternationUsingActionThread();
        }
        #endregion

在上面的代碼示例中,我們使用了帶有一個傳入參數的Action委托,當然了,匿名類型delegate(object myText)匿名代理了具有一個傳入參數的函數。
其實簡單點來說,可以像如下方式使用:
復制代碼 代碼如下:

this.Invoke((Action)(()=>
{
    button2.Text = text.ToString();
}));

這樣就顯得非常的方便。
最后一個當然是Predicate委托,和上面類似,只是寫起來麻煩一些,它需要一個傳入參數,并且返回一個bool類型:
復制代碼 代碼如下:

#region 利用Predicate實現線程和界面的交互
        private void AlternationUsingPrecidate(object text)
        {
//需要一個T類型的參數,返回bool類型
this.Invoke(new Predicate<object>(delegate(object myText) 
{
    myText = text;
    button3.Text = myText.ToString();
    return true;   //返回值
}),text);
        }
        private void AlternationUsingPrecidateThread()
        {
WaitCallback waitCallBack = new WaitCallback(this.AlternationUsingPrecidate);
ThreadPool.QueueUserWorkItem(waitCallBack,"Predicate的使用");
        }
        private void button3_Click(object sender, EventArgs e)
        {
AlternationUsingPrecidateThread();
        }
        #endregion

具體的注釋我已經寫在代碼中了,最后運行,能成功的將button3的Text置為“Predicate的使用.”
下面是全部實現代碼:
復制代碼 代碼如下:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
namespace DelegateIntegrateWinFormApp
{
    public partial class mainFrm : Form
    {
        public mainFrm()
        {
InitializeComponent();
        }
        private void mainFrm_Load(object sender, EventArgs e)
        {
/****************************注意例子中的使用方法****************
 * delegate TResult Func<TResult>();  無參,但是返回值為TResult類型
 * delegate void Action<T>(T1 arg1);  有一個參數arg1,但是無返回值
 * delegate bool Predicate<T>(T arg);  有一個參數arg,返回bool類型
 * **************************************************************/
        }
        #region 利用Func實現線程和界面交互
        private void AlternationUsingFunc(object text)
        {
//無參數,但是返回值為bool類型
this.Invoke(new Func<bool>(delegate()
{
    button1.Text = text.ToString();
    return true; //返回值
}));
        }
        private void AlternationUsingFuncThread()
        {
WaitCallback waitCallBack = new WaitCallback(this.AlternationUsingFunc);
ThreadPool.QueueUserWorkItem(waitCallBack, "Func的使用");
        }
        private void button1_Click(object sender, EventArgs e)
        {
AlternationUsingFuncThread();
        }
        #endregion

        #region 利用Action實現線程和界面交互
        private void AlternationUsingAction(object text)
        {
//需要一個T類型的參數,無返回值
this.Invoke(new Action<object>(delegate(object myText)
{
    myText = text;
    button2.Text = text.ToString();
}),text);
        }
        private void AlternationUsingActionThread()
        {
WaitCallback waitCallBack = new WaitCallback(this.AlternationUsingAction);
ThreadPool.QueueUserWorkItem(waitCallBack,"Action的使用");
        }
        private void button2_Click(object sender, EventArgs e)
        {
AlternationUsingActionThread();
        }
        #endregion
        #region 利用Predicate實現線程和界面的交互
        private void AlternationUsingPrecidate(object text)
        {
//需要一個T類型的參數,返回bool類型
this.Invoke(new Predicate<object>(delegate(object myText) 
{
    myText = text;
    button3.Text = myText.ToString();
    return true;   //返回值
}),text);
        }
        private void AlternationUsingPrecidateThread()
        {
WaitCallback waitCallBack = new WaitCallback(this.AlternationUsingPrecidate);
ThreadPool.QueueUserWorkItem(waitCallBack,"Predicate的使用");
        }
        private void button3_Click(object sender, EventArgs e)
        {
AlternationUsingPrecidateThread();
        }
        #endregion

    }
}


那么,現在對于WPF來說,該如何來使用呢?其實在WPF中,和winform中類似,只是在WPF中要實現線程和界面的交互,我們需要用Dispatcher來實現,也就是形如Control.Dispatcher.Invoke()的方式,由于與Winform實現方式無多大差別,這里我就直接附上全部代碼:
復制代碼 代碼如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Threading;
namespace WpfApplication1
{
    /// <summary>
    /// Interaction logic for Window1.xaml
    /// </summary>
    public partial class Window1 : Window
    {
        public Window1()
        {
InitializeComponent();
        }
        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
/****************************注意例子中的使用方法****************
* delegate TResult Func<TResult>();  無參,但是返回值為TResult類型
* delegate void Action();  無參,無返回值
* delegate bool Predicate<T>(T arg);  有一個參數arg,返回bool類型
* 需要注意,與WinForm中不同的是,WPF中需要利用Control.Dispatcher.Invoke來實現,其他類似.
* **************************************************************/
        }
        #region 利用Func實現線程和界面交互
        private void AlternationUsingFunc(object text)
        {
//無參數,但是返回值為bool類型
button1.Dispatcher.Invoke(new Func<bool>(delegate()
{
    button1.Content = text.ToString();
    return true; //返回值
}));
        }
        private void AlternationUsingFuncThread()
        {
WaitCallback waitCallBack = new WaitCallback(this.AlternationUsingFunc);
ThreadPool.QueueUserWorkItem(waitCallBack, "Func的使用");
        }
        private void button1_Click(object sender, RoutedEventArgs e)
        {
AlternationUsingFuncThread();
        }
        #endregion
        #region 利用Action實現線程和界面交互
        private void AlternationUsingAction(object text)
        {
//無參數,無返回值
//button2.Dispatcher.Invoke(new Action(delegate()
//{
//    button2.Content = text.ToString();
//}));
//或者
button2.Dispatcher.Invoke((Action)(()=>
{
    button2.Content = text.ToString();
}));
        }
        private void AlternationUsingActionThread()
        {
WaitCallback waitCallBack = new WaitCallback(this.AlternationUsingAction);
ThreadPool.QueueUserWorkItem(waitCallBack, "Action的使用");
        }
        private void button2_Click(object sender, RoutedEventArgs e)
        {
AlternationUsingActionThread();
        }
        #endregion
        #region 利用Predicate實現線程和界面的交互
        private void AlternationUsingPrecidate(object text)
        {
//需要一個T類型的參數,返回bool類型
this.button3.Dispatcher.Invoke(new Predicate<object>(delegate(object myText)
{
    myText = text;
    button3.Content = myText.ToString();
    return true;   //返回值
}), text);
        }
        private void AlternationUsingPrecidateThread()
        {
WaitCallback waitCallBack = new WaitCallback(this.AlternationUsingPrecidate);
ThreadPool.QueueUserWorkItem(waitCallBack, "Predicate的使用");
        }
        private void button3_Click(object sender, RoutedEventArgs e)
        {
AlternationUsingPrecidateThread();
        }
        #endregion

    }
}

逐個點擊界面上的按鈕,我們可以看到成功實現了線程和UI的交互:

當然,上面我們只是說到了在WinForm中和WPF中如何來使用的情況,代碼比較簡單,也沒有具體的應用場景,下面我們將結合中WPF來模擬一個具體的應用場景:
現在假設我有一個txt文檔,名稱為newEXO.txt,里面大概有5w行記錄,文件大小為30MB左右;同時我手邊還有一個oldEXO.txt里面也有5w數據,但是其中有一些記錄和newEXO.txt中的不同,我現在需要對比兩個txt文檔,找出不同的記錄,并對不同的記錄進行上色操作。
那么現在這里很明確了,我們需要兩個函數,一個是讀取記錄的函數ChangeText(),一個是上色的函數ChangeColor()。
但是在實際操作中,發現如果我直接利用wpf讀取數據的話,逐行讀取,耗時10s左右,也就是用戶界面會被阻塞10s,然后才會顯示給用戶,這個體驗性是相當不好的,所以擬采用異步方式來導入數據。
同時,考慮到差異比較也會比較耗時,所以也準備采用異步方式來進行對比。

那么問題來了,兩個均采用異步方式進行,難免會發生數據未導入完成就開始進行差異比較的可能,所以這里還涉及到一個線程同步的問題。
現在,這里有三個操作,異步的數據導入,異步的差異比較并上色,線程同步。

首先我們看異步導入,你也可以自己實現一個異步類,通過委托的BeginInvoke方法和EndInvoke方法來實現

復制代碼 代碼如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ThreadSynchorous
{
    public  class AsyncInvoke
    {
        public void BeginAsync(Func<bool> MyFunction)
        {
            Func<bool> func = new Func<bool>(MyFunction);
            IAsyncResult iar = func.BeginInvoke(new AsyncCallback(EndAsync), func);
        }
        public void EndAsync(IAsyncResult iar)
        {
            Func<bool> func = (Func<bool>)iar.AsyncState;
            func.EndInvoke(iar);
        }
    }
}

由于Action委托的使用方式最為便捷,這里我采用Action委托方式來進行,當然了,:
復制代碼 代碼如下:

private void ChangeText()
        {
            this.button1.Dispatcher.Invoke((Action)(()=>
            {
                string filename = @"C:/newEXO.txt";
                using (StreamReader sr = new StreamReader(filename, Encoding.Default))
                {
                    string result;
                    while ((result = sr.ReadLine()) != null)
                    {
                        //here perform action
                    }
                }
                //label1.Dispatcher.Invoke((new Action(delegate()
                label1.Dispatcher.Invoke((Action)(()=>
                {
                    label1.Content += "Loading finish!(Thread.CurrentThreadName=" + Thread.CurrentThread.ManagedThreadId.ToString() + ") ";
                }));
            }));
        }

首先是當點擊button1按鈕的時候,就啟動ChangeText()函數,也即數據導入函數,然后label1會在加載完畢的時候,給出提示信息。
下面再看看ChangeColor()函數:
復制代碼 代碼如下:

private void ChangeColor()
        {
            this.button1.Dispatcher.Invoke((Action)(()=>
            {
                this.button1.Background = Brushes.Red;
                //here perform large amount of data action and color the result
                label1.Dispatcher.Invoke((Action)(()=>
                {
                    label1.Content += "Coloring finish!(Thread.CurrentThreadName=" + Thread.CurrentThread.ManagedThreadId + ") ";
                }));
            }));
        }

可以看到也是當button1點擊的時候,會觸發ChangeColor函數。由于二者操作比較耗時,為了防止用戶界面阻塞,我們放到線程池中:
復制代碼 代碼如下:

ThreadPool.QueueUserWorkItem(o => ChangeText());
ThreadPool.QueueUserWorkItem(o => ChangeColor());

從上面可以看出,當點擊按鈕button1的時候,兩個函數同時被引發,也就是點擊按鈕的時候進行如下操作:
復制代碼 代碼如下:

private void button1_Click(object sender, RoutedEventArgs e)
        {
            ThreadPool.QueueUserWorkItem(o => ChangeText());
            ThreadPool.QueueUserWorkItem(o => ChangeColor());
            label1.Content += " /r/n-------------------------/r/n";
        }

看到了什么?

看到了線程運行的混亂,我們本想讓數據先加載,然后比較得出差異著色,可惜上面的結果中卻與想象中的相差甚遠.

這里的ChangeText()函數和ChangeColor()函數肯定不會像想象的那樣順序執行,那么代碼就有問題了,所以為了避免這個問題,我們必須進行線程同步,如何來進行呢? 方法很多,這里我采用EventWaitHandle方式來進行。

EventWaitHandle的Reset方式用來重置信號量,告訴其他運行的進程,你們需要被阻塞;Set方式用來釋放信號量,告訴其他運行的進程,你們的阻塞已經被解除,可以繼續運行了。

但是其他進行通過什么來知道自己是否可以解除阻塞狀態呢? 那就是利用WaitOne方式來判斷:

也就是按照如下的代碼模式來:

復制代碼 代碼如下:

EventWaitHandle waitMeHandle = new EventWaitHandle(false,EventResetMode.ManualReset);
private void ChangeText()
{
     waitMeHandle.Reset();  //即將進入下列執行過程,其他需要阻塞
  //....
     waitMeHandle.Set(); //釋放
}
private void ChangeColor()
{
      waitMeHandle.WaitOne(); //等待,直到接收到Set信號,才能運行
     //  ...
}

當然上面我舉出的例子只是一個Sample,我寫過這個軟件,利用的是BeginInvoke和EndInvoke方式實現的異步調用,有興趣可以參見我的這篇文章中提到的軟件:
下面是軟件截圖:

另外在寫這篇文章的時候,我在StackOverFlow上面有過提問,就是關于當前的Thread的ThreadId為什么一致的問題, 應該說兩個函數放到了ThreadPool中,結果出來的ThreadId應該不一樣才對呀.

其實,正確的答案是我的打印出ThreadId的信息都放在了label1.Dispatcher.Invoke這句話中,而這個Lable1屬于界面UI,也就是前臺線程,所以ThreadId會是一樣的,如果你直接在進入函數的時候,輸出ThreadId,你就會發現兩個函數運行在不同的線程上了.

下面是全部代碼:

復制代碼 代碼如下:

using System;
using System.Text;
using System.Windows;
using System.Windows.Media;
using System.Threading;
using System.IO;
namespace ThreadSynchorous
{
    public partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent();
            asyncInvoke = new AsyncInvoke();
        }
        AsyncInvoke asyncInvoke;
        EventWaitHandle waitMeHandle = new EventWaitHandle(false,EventResetMode.ManualReset);
        private void button1_Click(object sender, RoutedEventArgs e)
        {
            ThreadPool.QueueUserWorkItem(o => ChangeText());
            ThreadPool.QueueUserWorkItem(o => ChangeColor());
            label1.Content += " /r/n-------------------------/r/n";
        }

        private void ChangeText()
        {
            waitMeHandle.Reset();  //即將進入下列執行過程,其他需要阻塞
            this.button1.Dispatcher.Invoke((Action)(()=>
            {
                string filename = @"C:/MyLearn/eqrms_hk_20111219_listedposn_ff/EQRMS_HK_20111219_EXO.txt";
                using (StreamReader sr = new StreamReader(filename, Encoding.Default))
                {
                    string result;
                    while ((result = sr.ReadLine()) != null)
                    {
                        //here perform action
                    }
                }
                label1.Dispatcher.Invoke((Action)(()=>
                {
                    label1.Content += "Loading finish!(Thread.CurrentThreadName=" + Thread.CurrentThread.ManagedThreadId.ToString() + ") ";
                    waitMeHandle.Set(); //釋放
                }));
            }));
        }

        private void ChangeColor()
        {
            waitMeHandle.WaitOne(); //等待,直到接收到Set信號,才能運行
            this.button1.Dispatcher.Invoke((Action)(()=>
            {
                this.button1.Background = Brushes.Red;
                //here perform large amount of data action and color the result
                label1.Dispatcher.Invoke((Action)(()=>
                {
                    label1.Content += "Coloring finish!(Thread.CurrentThreadName=" + Thread.CurrentThread.ManagedThreadId + ") ";
                }));
            }));
        }
    }
}

本文中涉及到的源碼,可以從這里下載

 

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
7777免费精品视频| 国产成人在线精品| 亚洲国产成人爱av在线播放| 国产一区二区在线播放| 亚洲黄色在线观看| 国产午夜精品全部视频在线播放| 欧美怡红院视频一区二区三区| 黄网动漫久久久| 日韩美女在线观看一区| 亚洲第一av在线| 午夜精品一区二区三区av| 麻豆国产精品va在线观看不卡| 97热在线精品视频在线观看| 久久噜噜噜精品国产亚洲综合| 午夜精品福利在线观看| 91久久精品国产91久久性色| 亚洲字幕一区二区| 欧美视频在线免费看| 中文字幕视频在线免费欧美日韩综合在线看| 久久久久久久久国产| 久久偷看各类女兵18女厕嘘嘘| 欧美精品第一页在线播放| 国产欧美精品va在线观看| 精品国产自在精品国产浪潮| 国产成人一区二区三区电影| 欧美午夜xxx| 亚洲一区二区免费在线| 亚洲欧美中文日韩在线v日本| 亚洲理论在线a中文字幕| 亚洲国产精品va| 插插插亚洲综合网| 欧美激情一区二区三区高清视频| 性视频1819p久久| 中文字幕在线视频日韩| 欧美一级大片在线免费观看| 久久精品欧美视频| 亚洲欧洲美洲在线综合| 国产欧美精品一区二区三区-老狼| 久久99亚洲精品| 欧美激情亚洲国产| 欧美猛少妇色xxxxx| 尤物精品国产第一福利三区| 日韩电影中文 亚洲精品乱码| 国产玖玖精品视频| 红桃av永久久久| 久久久久久国产| 91中文在线观看| 亚洲人成网站999久久久综合| 欧美与欧洲交xxxx免费观看| 亚洲精品乱码久久久久久按摩观| 国产成人一区三区| 中文字幕在线看视频国产欧美在线看完整| 久久中文字幕一区| 在线观看国产成人av片| 国产成人avxxxxx在线看| 久久久久免费视频| 日韩在线观看免费高清完整版| 午夜美女久久久久爽久久| 日韩成人在线免费观看| 亚洲精品aⅴ中文字幕乱码| 91午夜在线播放| 欧美高清理论片| 欧美日韩在线视频观看| 欧美成人精品不卡视频在线观看| 欧美做爰性生交视频| 在线电影中文日韩| 国产精品爽黄69| 欧美激情成人在线视频| 日韩中文字幕久久| 久久不射热爱视频精品| 国产亚洲a∨片在线观看| 亚洲国产黄色片| 国产精品一区二区三区久久久| 欧美成人免费全部观看天天性色| 中文字幕久热精品视频在线| 国产精品直播网红| 情事1991在线| 尤物yw午夜国产精品视频明星| 亚洲天堂免费视频| 日本国产精品视频| 亚洲欧洲在线播放| 精品国产乱码久久久久酒店| 国产精品69久久久久| 中文字幕国产精品| 国产精品jizz在线观看麻豆| 国产欧美在线视频| 国产精品久久国产精品99gif| 成人中文字幕在线观看| 97精品一区二区视频在线观看| 日韩在线播放视频| 亚洲精品xxx| 亚洲人成网站免费播放| 尤物九九久久国产精品的特点| 日本欧美中文字幕| 日韩精品黄色网| 久久久精品在线| 日韩av中文字幕在线免费观看| 国产在线观看91精品一区| 操人视频在线观看欧美| 日本午夜精品理论片a级appf发布| 国产在线播放不卡| 欧美成人激情视频免费观看| 亚洲精品www久久久久久广东| 国产欧美日韩专区发布| 国产精品国产三级国产aⅴ9色| 日韩电影中文字幕在线| 亚洲男人天堂古典| 国产精品久久国产精品99gif| 一区二区三区 在线观看视| 狠狠躁夜夜躁人人躁婷婷91| 亚洲小视频在线| 亚洲精品自拍视频| 色阁综合伊人av| 78m国产成人精品视频| 国产成人在线亚洲欧美| 国产精品高潮呻吟久久av野狼| 91理论片午午论夜理片久久| 国产精品久久久久不卡| 国产精品精品久久久久久| 亚洲成人激情在线观看| 555www成人网| 亚洲免费电影在线观看| 久久精品久久精品亚洲人| 日韩经典中文字幕| 精品国产欧美一区二区五十路| 欧美日韩免费在线观看| 亚州欧美日韩中文视频| 欧美精品videosex极品1| 久久亚洲精品小早川怜子66| www.欧美三级电影.com| 国内精品视频在线| 国产97在线观看| 97色在线观看免费视频| 91久热免费在线视频| 91精品国产91久久久久| 久久久久久久亚洲精品| 尤物九九久久国产精品的特点| 中文字幕精品一区久久久久| 欧美午夜久久久| 777777777亚洲妇女| 中文字幕亚洲图片| 国产精品久久久久久久久久99| 国产成人精品综合| 日韩欧美中文第一页| 亚洲直播在线一区| 亚洲香蕉伊综合在人在线视看| 78m国产成人精品视频| 国产一区香蕉久久| 亚洲欧洲日韩国产| 亚洲风情亚aⅴ在线发布| 亚洲一区二区三区乱码aⅴ蜜桃女| 在线观看欧美日韩| 亚洲国产日韩欧美综合久久| 亚洲精品中文字幕有码专区| 国外成人免费在线播放| 成人午夜黄色影院| 亚洲天堂av电影| 亚洲精品98久久久久久中文字幕| 91影视免费在线观看| 亚洲精品aⅴ中文字幕乱码| 中文字幕视频在线免费欧美日韩综合在线看| 国产女同一区二区| 4438全国亚洲精品在线观看视频| 精品成人在线视频|