线程学习1——异步委托

一.为什么使用线程

    简单来讲,就是用线程来实现,在程序运行过程中,还可以同时执行其他操作。

二.线程的概述

    线程是程序中独立的指令流。使用C#编写任何程序时,都有一个入口:Main()方法。程序从Main()方法的第一条语句开始执行,直到这个方法返回为止。

    在.net framework class library中,所有与多线程机制应用相关的类都是放在System.Threading命名空间中的。

    如果你想在你的应用程序中使用多线程,就必须包含这个类。

三.异步委托

    创建线程的一个简单方式是定义一个委托,异步调用它。

    那什么是异步委托呢?异步委托就是定义一个方法,开一个新线程,让这个方法在后台执行。

    委托是方法的类型安全引用。Delegate类支持异步调用的方法,在后台Delegate类会创建一个执行任务的线程。

第一步:定义方法和委托

    我们先定义一个需要一定时间才能完成的方法:TakesTime(int data,int ms),这个方法调用Thread.Sleep方法,至少需要经过传入的参数ms毫秒后才能执行完。

 
  
public static int TakesTime( int data, int ms)
{
Console.WriteLine(
" TakesTime started " );
Thread.Sleep(ms);
Console.WriteLine(
" \nTakesTime complated " );
return ++ data;
}

     要在委托中调用这个方法,必须定义一个有相同参数和返回类型的委托:

 public delegate int TakesTimeDelegate(int data, int ms);

第二步:等待委托的结果的方式

     第一种方式——投票(检测委托,即反复询问)

     将方法交给后台执行后,我们仍可以检查委托的一些执行状态,如下面所示的是否完成(IsComplated)。

     所创建的Delegate类提供了BeginInvoke()方法,在该方法中,可以传递用委托类型定义的输入参数。BeginInvoke()方法总是有两个AsyncCalllback和Object类型的额外参数。

     其返回类型为 IAsyncResult。通过这个返回结果可以获得该委托的相关信息。下面是用了IsComplated方法检查委托是否完成,只要委托没有完成程序将一直执行:

 
  
static void Main( string [] args)
{
TakesTimeDelegate mTakesTime
= TakesTime;
// 将任务交给后台执行
IAsyncResult mIAsyncResult = mTakesTime.BeginInvoke( 1 , 9000 , null , null );
// 等待后台线程结束
while ( ! mIAsyncResult.IsCompleted)
{
Console.Write(
" . " );
Thread.Sleep(
50 );
}
int result = mTakesTime.EndInvoke(mIAsyncResult);
// 获取返回结果
Console.WriteLine( " Result:{0} " , result);
Console.ReadLine();
}

      运行程序时,委托线程和主线程同时运行,委托线程完毕后,主线程的循环就停止了。同时也可以在主线程中调用EndInvoke方法结束后台线程。

      如果后台线程没有完成,EndInvoke方法会一直等待,直到后台线程完成或者主线程结束。

      第二种方式——等待句柄(等待一段时间后在询问

      等待异步委托的结果的另一种方法就是使用IAsyncReault相关联的等待句柄。使用AsyncWaitHandle属性就可以访问等待句柄。这个属性返回WaitHandle类型的对象,

      它可以等待委托线程完成其任务。WaitOne()方法将一个超时时间作为可选的第一个参数,在其中可以定义要等待的最长时间。如果发生超时WaitOne方法就返回false。    

 
  
static void Main( string [] args)
{
TakesTimeDelegate mTakesTime
= TakesTime;
IAsyncResult mIAsyncResult
= mTakesTime.BeginInvoke( 1 , 3000 , null , null );
while ( true )
{
Console.Write(
" . " );
if (mIAsyncResult.AsyncWaitHandle.WaitOne( 50 , false ))
{
Console.WriteLine(
" Can get the result now " );
break ;
}
}
int result = mTakesTime.EndInvoke(mIAsyncResult);
Console.WriteLine(
" Reault: {0} " , result);
Console.ReadLine();
}

       第三种方式——异步回调 

       异步回调是指:将任务委托给后台一个线程,这个任务结束后,自动调用一个已定义的方法,而不需要在主线程中等待结果。

       在BeginInvoke()方法的第三个参数中,可以传递一个满足IAsyncCallback委托需要的方法。在该委托方法执行完之后,后台线程会调用这个方法,二不需要在主线程中等待后台线程的结果。

       IAsyncCallback委托定义了一个IAsyncResult类型的参数,其返回类型为void。以下的代码中,我们先定义一个TakesTimeComplated()方法,用作回调方法。

 
  
public static void TakesTimeComplated(IAsyncResult ar)
{
if (ar == null )
{
throw new ArgumentNullException( " ar " );
}
TakesTimeDelegate t3
= ar.AsyncState as TakesTimeDelegate;
Trace.Assert(t3
!= null , " 对象类型不对 " );
int result = t3.EndInvoke(ar);
Console.WriteLine(
" result {0} " , result);
}

         之后我们在主线程中启动这个方法:

 
  
static void Main( string [] args)
{
TakesTimeDelegate t3
= TakesTime;
t3.BeginInvoke(
1 , 3000 , TakesTimeComplated, t3);
for ( int i = 0 ; i < 100 ; i ++ )
{
Console.Write(
" . " );
Thread.Sleep(
50 );
}
Console.ReadLine();
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值