温故知新 C# 异步
1.用Thread实现异步
{
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 { get; set; }
//开始异步调用
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
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来判断异步调用是否完成,类似于下面的代码
{
}
也可以用ar.AsyncWaitHandle.WaitOne();
如果没完成,就阻塞当前线程。
如果完成了异步调用,就返回指定类型的值或者不返回值(取决于代理的定义:public delegate string AsyncDelegate(string str);)
也可以不在callBack的方法中调用EndInvoke,直接在主线程中调用EndInvoke,但是这样就会阻塞主线程,直到异步调用完成。
3..NET Framework中一些常用类库也提供了BeginXXX和EndXXX的异步调用
例如常见的SqlCommand、WebRequest、FileStream、WebServcie等等。