先用一个实例来说明一下异步。通俗地讲,异步就是在同一个时间段里可以做多件事情,比如同一时间做饭(Cooking)、烧水(Boiling)、洗衣服(Washing)。方法BeginInvoke()新开一个线程进行异步调用;EndInvoke()阻塞执行一直到方法完成取得返回值。
实例1:做饭(8s)-烧水(5s)-洗衣服(3s),每开始和结束一件事情就报告一下
方法:利用函数代理的BeginInvoke()异步执行该代理所指向的方法。如:
cook.BeginInvoke(null, null);
boil.BeginInvoke(null, null);
wash.BeginInvoke(null, null);
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(null, null);
IAsyncResult iarBoil = boil.BeginInvoke(null, null);
IAsyncResult iarWash = wash.BeginInvoke(null, null);
//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, null, null);
//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, null, null);
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, null, null);
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 == null) return;
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);
}
}
}