温故知新 C# 异步

1.用Thread实现异步

    class Program
    {
        
public delegate void EndAsyncDelegate(string str);

        
static void Main(string[] args)
        {
            Console.WriteLine(
"Ready Invoke Async Method!");

            Console.WriteLine(
"Begin!");

            BeginAsyncInvoke();

            Console.WriteLine(
"Continue!");

            Console.ReadKey();
        }

        
static void BeginAsyncInvoke()
        {
            EndAsyncDelegate myDelegate 
= EndAsyncInvoke;//异步完成后要执行的

            ClassForAsync c1 
= new ClassForAsync(myDelegate);

            ParameterizedThreadStart myThreadStart 
= new ParameterizedThreadStart(c1.Class1ThreadMethod);

            Thread myThread 
= new Thread(myThreadStart);

            myThread.Start(
"123"); //参数"123"
        }

        
static void EndAsyncInvoke(string str)
        {
            Console.WriteLine(
"完成--异步调用!");

            Console.WriteLine(
"异步执行结果 -- AsyncResultStr:{0}", str);
        }

        
public class ClassForAsync
        {
            
private EndAsyncDelegate OnAsyncDelegateEnd;

            
public ClassForAsync(EndAsyncDelegate myDelegate)
            {
                
this.OnAsyncDelegateEnd = myDelegate;
            }

            
public string AsyncResultStr { getset; }

            
//开始异步调用
            public void Class1ThreadMethod(object obj)
            {
                Console.WriteLine(
"开始--异步调用!");

                AsyncResultStr 
= obj.ToString();

                
this.OnAsyncDelegateEnd(AsyncResultStr);//触发异步完成调用的方法
            }
        }
    }

这里,我通过构建Thread对象来进行异步,它的参数是一个代理ParameterizedThreadStart myThreadStart = new ParameterizedThreadStart(c1.Class1ThreadMethod); 这个代理接收一个obj类型的参数。另外,Thread还接收另外一个没有参数的代理ThreadStart,可以用来做你不需要参数的动作。

当异步做完要执行的动作后,就通过this.OnAsyncDelegateEnd(AsyncResultStr);来调用异步完成后的动作,这个只是思路,耦合度还是挺高的,有很大的修改空间。

 

2.Delegate的BeginInvoke,EndInvoke

public delegate string AsyncDelegate(string str);

        
static void Main(string[] args)
        {
          
            AsyncInvoke();

            Console.ReadKey();
        }

        
static void AsyncInvoke()
        {
            AsyncDelegate a 
= AsyncDelegateMethod;

            AsyncCallback callBack
=new AsyncCallback(AsyncDelegateCallBackMethod);

            Console.WriteLine(
"Start!(Before Async Invoke)");

            IAsyncResult ar
= a.BeginInvoke("test123", callBack,a);

            Console.WriteLine(
"Do something else..");

            Console.WriteLine(
"Continue(After Async Invoke)");

        }

        
//异步调用开始方法
        static string AsyncDelegateMethod(string str)
        {
            Console.WriteLine(
"Begin - Async Invoke!");

            
return str;
        }

        
static void AsyncDelegateCallBackMethod(IAsyncResult ar)
        {
            
//异步调用完成后要做的动作
            AsyncDelegate a = ar.AsyncState as AsyncDelegate;

            
if (a != null)
            {
                
string str = a.EndInvoke(ar);

                Console.WriteLine(str);
            }

            Console.WriteLine(
"End -Async Invoke!");
        }

用a.BeginInvoke("test123", callBack,a);来进行异步调用,其中:

(1)"test123"是传递给异步调用方法的参数

(2)callBack 是用于异步调用完成后要调用的方法,它是一个AsyncCallback对象(Delegate类型的)

(3)a是Object类型,这里我把AsyncDelegate对象传入,这样就可以在static void AsyncDelegateCallBackMethod(IAsyncResult ar)方法中,

通过AsyncDelegate a = ar.AsyncState as AsyncDelegate;获取到AsyncDelegate对象,然后调用a.EndInvoke(ar)法获取返回值。

a.EndInvoke(ar)内部会调用ar.IsCompleted来判断异步调用是否完成,类似于下面的代码

while (!ar.IsCompleted)
{
}
//do something

也可以用ar.AsyncWaitHandle.WaitOne();

如果没完成,就阻塞当前线程。

如果完成了异步调用,就返回指定类型的值或者不返回值(取决于代理的定义:public delegate string AsyncDelegate(string str);)

也可以不在callBack的方法中调用EndInvoke,直接在主线程中调用EndInvoke,但是这样就会阻塞主线程,直到异步调用完成。

 

3..NET Framework中一些常用类库也提供了BeginXXX和EndXXX的异步调用

   例如常见的SqlCommandWebRequest、FileStream、WebServcie等等。

 

posted @ 2011-07-04 16:16  ._  阅读(809)  评论(0编辑  收藏  举报