C#中的BeginInvoke和EndInvoke实现异步

来源:互联网 发布:知乎手机怎么回答 编辑:程序博客网 时间:2024/05/16 04:56

先用一个实例来说明一下异步。通俗地讲,异步就是在同一个时间段里可以做多件事情,比如同一时间做饭(Cooking)、烧水(Boiling)、洗衣服(Washing)。方法BeginInvoke()新开一个线程进行异步调用;EndInvoke()阻塞执行一直到方法完成取得返回值。

 

实例1:做饭(8s)-烧水(5s)-洗衣服(3s),每开始和结束一件事情就报告一下

方法:利用函数代理的BeginInvoke()异步执行该代理所指向的方法。如:

cook.BeginInvoke(nullnull);

boil.BeginInvoke(nullnull);

wash.BeginInvoke(nullnull);

Code

namespace AsyncApp

{

    public delegate void work();

    public delegate void write(string s);

    /// <summary>

    /// test1:做饭(8s)-烧水(5s)-洗衣服(3s),每开始和结束一件事情就报告一下

    /// </summary>

    public partial class frmAsync : Form

    {

        private work wash;

        private work boil;

        private work cook;

        private write writeIntoRTB;

        public frmAsync()

        {

            InitializeComponent();

            wash = new work(washing);

            boil = new work(boiling);

            cook = new work(cooking);

            rtb.Text = "";

        }

        //btOK

        private void btOK_Click(object sender, EventArgs e)

        {

            Run();

        }

        private void Run()

        {

            IAsyncResult iarCook = cook.BeginInvoke(nullnull);

            IAsyncResult iarBoil = boil.BeginInvoke(nullnull);

            IAsyncResult iarWash = wash.BeginInvoke(nullnull);

            //wash.EndInvoke(iarWash);

            //boil.EndInvoke(iarBoil);

            //cook.EndInvoke(iarCook);

        }

        private void washing()

        {

            string strWashStart = string.Format("I start washing at {0}.", System.DateTime.Now);

            Console.WriteLine(strWashStart);

            RefreshRTB(strWashStart);

            System.Threading.Thread.Sleep(3000);

            string strWashEnd = string.Format("I finish washing at {0}.", System.DateTime.Now);

            Console.WriteLine(strWashEnd);

            RefreshRTB(strWashEnd);

        }

        private void boiling()

        {

            string strBoilStart = string.Format("I start boiling at {0}.", System.DateTime.Now);

            Console.WriteLine(strBoilStart);

            RefreshRTB(strBoilStart);

            System.Threading.Thread.Sleep(5000);

            string strBoilEnd = string.Format("I finish boiling at {0}.", System.DateTime.Now);

            Console.WriteLine(strBoilEnd);

            RefreshRTB(strBoilEnd);

        }

        private void cooking()

        {

            string strCookStart = string.Format("I start cooking at {0}.", System.DateTime.Now);

            Console.WriteLine(strCookStart);

            RefreshRTB(strCookStart);

            System.Threading.Thread.Sleep(8000);

            string strCookEnd = string.Format("I finish cooking at {0}.", System.DateTime.Now);

            Console.WriteLine(strCookEnd);

            RefreshRTB(strCookEnd);

        }

        private void RefreshRTB(string s)

        {

            if (rtb.InvokeRequired)

            {

                writeIntoRTB = new write(RefreshRTB);

                rtb.BeginInvoke(writeIntoRTB, s);

            }

            else

            {

                writeIn(s);

            }

        }

        private void writeIn(string s)

        {

            rtb.Text = s + "/n" + rtb.Text;

            rtb.Refresh();

        }

        private void btTest_Click(object sender, EventArgs e)

        {

            writeIn("yangqinzhi");

        }

        #endregion

}

 

实例2~4:利用EndInvoke的属性和方法

方法:

1. 直接使用EndInvoke方法来获得返回值:当使用BeginInvoke异步调用方法时,如果方法未执行完,EndInvoke方法就会一直阻塞,直到被调用方法执行完毕。(见实例2)

2. 使用IAsyncResult的IsCompleted属性来判断异步调用是否完成。(见实例3)

while ( ! IAsyncResult.IsCompleted )

{

//每100ms判断一次是否完成

Thread.Sleep(100);

}

3. 使用WaitOne方法等待异步方法执行完成。(见实例4)

//每100ms判断一次是否完成

while ( ! IAsyncResult.AsyncWaitHandle.WaitOne (100,false) )

{

//Thread.Sleep(100);

}

 

实例2 Code

namespace AsyncApp

{

    public delegate int NewTaskDelegate(int ms);

/// <summary>  

/// test2:直接使用EndInvoke方法来获得返回值

    /// </summary>

    public partial class frmAsync : Form

    {

        private NewTaskDelegate task;

        public frmAsync()

        {

            InitializeComponent();

            task = new NewTaskDelegate(newTask);

        }

        private int newTask(int ms)

        {

            Console.WriteLine("Task begin!" + System.DateTime.Now);

            System.Threading.Thread.Sleep(ms);

            System.Random random = new Random();

            int n = random.Next(1000);

            Console.WriteLine("Task finished!" + System.DateTime.Now);

            return n;

        }

        //ok

        private void btStart_Click(object sender, EventArgs e)

        {

            Console.WriteLine("Time-0:" + System.DateTime.Now);

            System.Threading.Thread.Sleep(10000);

            Console.WriteLine("Time-1:" + System.DateTime.Now);

            IAsyncResult iar = task.BeginInvoke(2000, nullnull);

            //block 2ms

            Console.WriteLine("Time-2:" + System.DateTime.Now);

            int result = task.EndInvoke(iar);

            Console.WriteLine("Time-3:" + System.DateTime.Now);

            Console.WriteLine(result);

        }

}

 

实例3 Code:

namespace AsyncApp

{

    public delegate int NewTaskDelegate(int ms);

    /// <summary>

    /// test3:使用IAsyncResult的IsCompleted属性来判断异步调用是否完成。

    /// </summary>

    public partial class frmAsync : Form

    {

        private NewTaskDelegate task;

        public frmAsync()

        {

            InitializeComponent();

            task = new NewTaskDelegate(newTask);

        }

        private int newTask(int ms)

        {

            Console.WriteLine("Task begin!" + System.DateTime.Now);

            System.Threading.Thread.Sleep(ms);

            System.Random random = new Random();

            int n = random.Next(1000);

            Console.WriteLine("Task finished!" + System.DateTime.Now);

            return n;

        }

        private void bt3_Click(object sender, EventArgs e)

        {

            IAsyncResult iar = task.BeginInvoke(2000, nullnull);

            while (!iar.IsCompleted)

            {

                Console.WriteLine("waiting...");

                System.Threading.Thread.Sleep(500);

            }

            int result = task.EndInvoke(iar);

            Console.WriteLine(result);

        }

}

 

实例4 Code:

namespace AsyncApp

{

    public delegate int NewTaskDelegate(int ms);

    /// <summary>

    /// test4:使用WaitOne方法等待异步方法执行完成。

    /// </summary>

    public partial class frmAsync : Form

    {

        private NewTaskDelegate task;

        public frmAsync()

        {

            InitializeComponent();

            task = new NewTaskDelegate(newTask);

        }

        private int newTask(int ms)

        {

            Console.WriteLine("Task begin!" + System.DateTime.Now);

            System.Threading.Thread.Sleep(ms);

            System.Random random = new Random();

            int n = random.Next(1000);

            Console.WriteLine("Task finished!" + System.DateTime.Now);

            return n;

        }

        private void bt4_Click(object sender, EventArgs e)

        {

            IAsyncResult iar = task.BeginInvoke(2000, nullnull);

            while (!iar.AsyncWaitHandle.WaitOne(100,false))

            {

                Console.WriteLine("waiting...");

                System.Threading.Thread.Sleep(500);

            }

            int result = task.EndInvoke(iar);

            Console.WriteLine(result);

        }

}

 

实例5:利用BeginInvoke回调函数

方法:

IAsyncResult delegate.BeginInvoke ( AsyncCallback callback, object @object )

1. 代理的回调方法,也就是说当代理my执行完毕后,再调用MethodComplete函数,MethodComplete的参数由BeginInvoke的第二个参数my提供。

IAsyncResult iar = my.BeginInvoke(MethodComplete, my);

2. 控件的回调方法

tb5.BeginInvoke(writeIntoTB, (iar.AsyncState as MyMethod).EndInvoke(iar).ToString());

Code

namespace AsyncApp

{

    public delegate void write(string s);

    public delegate int MyMethod();

    /// <summary>

    /// test5:利用BeginInvoke的回调函数

    /// </summary>

    public partial class frmAsync : Form

    {

        private MyMethod my;

        public frmAsync()

        {

            InitializeComponent();

            my = new MyMethod(method);

        }

        

        private int method()

        {

            System.Threading.Thread.Sleep(5000);

            return 100;

        }

        //表示调用方法完成之后,执行的操作(回调函数)

        private void MethodComplete(IAsyncResult iar)

        {

            if (iar == nullreturn;

            if (tb5.InvokeRequired)

            {

                write writeIntoTB = new write(RefreshTB);

                tb5.BeginInvoke(writeIntoTB, (iar.AsyncState as MyMethod).EndInvoke(iar).ToString());

            }

            else

            {

                RefreshTB((iar.AsyncState as MyMethod).EndInvoke(iar).ToString());

            }

        }

        private void RefreshTB(string s)

        {

            tb5.Clear();

            tb5.Text = s;

        }

        //ok

        private void bt5_Click(object sender, EventArgs e)

        {

            IAsyncResult iar = my.BeginInvoke(MethodComplete, my);

        }

    }

}

原创粉丝点击