您的位置:首页 > 编程语言 > C#

C# 异步委托 (转)最近学习这个,所以收集了些

2011-09-26 14:50 381 查看
当我们的程序顺序执行的时候,如果我们调用了一个很耗时的方法,那么应用程序会使当前的线程处于阻塞状态,直到方法的调用完成再继续执行。这样的方法调用被认为是同步的。如果我们调用了一个远程的方法,那么这个方法的调用可能花费的时间会更长。如果我们不想立即取得方法所返回的结果,或者我们根本就不让方法返回结果的话,这种等待是没有必要的。

如果我们想调用一个这样的方法,当调用之后就立即返回,假如在调用期间发生了异常,我们可以在稍后的时间重起该方法的动作。那我们就可以利用异步委托来把我们的方法做成异步的调用。

每个委托都有三个方法:Invoke、BeginInvoke、EndInvoke。

第一个方法是委托指定函数的同步调用,另外两个是异步调用。

如果我们自己写了个委托

public delegate string MyDelegate(string name);

那么C#就会自动为我们提供了下面两个方法:

IAsyncResult BeginInvoke(string name,AsyncResult callback,Object o)

以及

string EndInvoke(IAsyncResult result);



以上内容摘自http://www.cnblogs.com/wenwuxianren/archive/2008/04/17/1158504.html

http://www.cnblogs.com/everx/archive/2007/02/01/519218.html



下面是MSDN上的官方解释

异步委托提供以异步方式调用同步方法的能力。当同步调用一个委托时,“Invoke”方法直接对当前线程调用目标方法。如果编译器支持异步委托,则它将生成“Invoke”方法以及“BeginInvoke”和“EndInvoke”方法。如果调用“BeginInvoke”方法,则公共语言运行库 (CLR) 将对请求进行排队并立即返回到调用方。将对来自线程池的线程调用该目标方法。提交请求的原始线程自由地继续与目标方法并行执行,该目标方法是对线程池线程运行的。如果在对“BeginInvoke”方法的调用中指定了回调方法,则当目标方法返回时将调用该回调方法。在回调方法中,“EndInvoke”方法获取返回值和所有输入/输出参数。如果在调用“BeginInvoke”时未指定任何回调方法,则可以从调用“BeginInvoke”的线程中调用“EndInvoke”。

.NET Framework 允许您异步调用任何方法。为此,应定义与您要调用的方法具有相同签名的委托;公共语言运行库会自动使用适当的签名为该委托定义 BeginInvoke 和 EndInvoke 方法。

BeginInvoke 方法可启动异步调用。它与您需要异步执行的方法具有相同的参数,另外它还有两个可选参数。第一个参数是一个 AsyncCallback 委托,该委托引用在异步调用完成时要调用的方法。第二个参数是一个用户定义的对象,该对象可向回调方法传递信息。BeginInvoke 立即返回,不等待异步调用完成。BeginInvoke 会返回 IAsyncResult,这个结果可用于监视异步调用进度。

EndInvoke 方法检索异步调用的结果。调用 BeginInvoke 后可随时调用 EndInvoke 方法;如果异步调用尚未完成,EndInvoke 将一直阻止调用线程,直到异步调用完成后才允许调用线程执行。EndInvoke 的参数包括您需要异步执行的方法的 out 和 ref 参数(在 Visual Basic 中为 <Out> ByRef 和 ByRef)以及由 BeginInvoke 返回的 IAsyncResult。

接下来,MSDN提供了两个例子:



第一个例子是:

using System;

using System.Collections.Generic;

using System.Text;

using System.Threading;



namespace AsyncDemo

{

class Program

{

public class AsyncDemo

{

// 这个方法将被异步调用

public string TestMethod(int callDuration, out int threadId)

{

Console.WriteLine("Test method begins.");

Thread.Sleep(callDuration);

threadId = Thread.CurrentThread.ManagedThreadId;

return String.Format("My call time was {0}.", callDuration.ToString());

}

}

// 异步调用方法的委托,这个委托必须与TestMethod有同样的签名

public delegate string AsyncMethodCaller(int callDuration, out int threadId);





public static void Main()

{

// 异步调用方法将把它的thread id放在这里

int threadId;



// 构建一个测试实例

AsyncDemo ad = new AsyncDemo();



// 构建委托

AsyncMethodCaller caller = new AsyncMethodCaller(ad.TestMethod);



// 开始执行异步委托

IAsyncResult result = caller.BeginInvoke(3000,

out threadId, null, null);



Thread.Sleep(0);

Console.WriteLine("Main thread {0} does some work.",

Thread.CurrentThread.ManagedThreadId);



// EndInvoke一直阻塞,一直到异步调用完成之后才返回

// 并且取到了异步调用的返回值

string returnValue = caller.EndInvoke(out threadId, result);



Console.WriteLine("The call executed on thread {0}, with return value \"{1}\".",

threadId, returnValue);

}



}

}

第二个例子是:

using System;

using System.Threading;

using System.Runtime.Remoting.Messaging;

using System.Collections.Generic;

using System.Text;



namespace DelegationTest

{

// 构造一个异步调用方法来分解因式

class PrimeFactorFinder

{

public static bool Factorize(

int number,

ref int primefactor1,

ref int primefactor2)

{

primefactor1 = 1;

primefactor2 = number;



// Factorize using a low-tech approach.

for (int i = 2; i < number; i++)

{

if (0 == (number % i))

{

primefactor1 = i;

primefactor2 = number / i;

break;

}

}

if (1 == primefactor1)

return false;

else

return true;

}



}



// 构建一个异步委托来匹配异步调用方法

public delegate bool AsyncFactorCaller(

int number,

ref int primefactor1,

ref int primefactor2);



public class DemonstrateAsyncPattern

{

// The waiter object used to keep the main application thread

// from terminating before the callback method completes.

ManualResetEvent waiter;



// Define the method that receives a callback when the results are available.

public void FactorizedResults(IAsyncResult result)

{

int factor1 = 0;

int factor2 = 0;



// Extract the delegate from the

// System.Runtime.Remoting.Messaging.AsyncResult.

AsyncFactorCaller factorDelegate = (AsyncFactorCaller)((AsyncResult)result).AsyncDelegate;

int number = (int)result.AsyncState;

// Obtain the result.

bool answer = factorDelegate.EndInvoke(ref factor1, ref factor2, result);

// Output the results.

Console.WriteLine("On CallBack: Factors of {0} : {1} {2} - {3}",

number, factor1, factor2, answer);

waiter.Set();

}



// 下面的方法演示了在异步调用中利用回调函数的方法(异步调用执行完成之后执行回调方法)

public void FactorizeNumberUsingCallback()

{

AsyncFactorCaller factorDelegate = new AsyncFactorCaller(PrimeFactorFinder.Factorize);

int number = 1000589023;

int temp = 0;

// Waiter will keep the main application thread from

// ending before the callback completes because

// the main thread blocks until the waiter is signaled

// in the callback.

waiter = new ManualResetEvent(false);



// Define the AsyncCallback delegate.

AsyncCallback callBack = new AsyncCallback(this.FactorizedResults);



// Asynchronously invoke the Factorize method.

IAsyncResult result = factorDelegate.BeginInvoke(

number,

ref temp,

ref temp,

callBack,

number);



// Do some other useful work while

// waiting for the asynchronous operation to complete.



// When no more work can be done, wait.

waiter.WaitOne();

}



// 下面的方法演示了异步调用时使用轮询方法而非回调方法(会比回调方法效率低一些)

public void FactorizeNumberAndWait()

{

AsyncFactorCaller factorDelegate = new AsyncFactorCaller(PrimeFactorFinder.Factorize);



int number = 1000589023;

int temp = 0;



// Asynchronously invoke the Factorize method.

IAsyncResult result = factorDelegate.BeginInvoke(

number,

ref temp,

ref temp,

null,

null);



while (!result.IsCompleted)

{

// Do any work you can do before waiting.

result.AsyncWaitHandle.WaitOne(10000, false);

}

// The asynchronous operation has completed.

int factor1 = 0;

int factor2 = 0;



// Obtain the result.

bool answer = factorDelegate.EndInvoke(ref factor1, ref factor2, result);



// Output the results.

Console.WriteLine("Sequential : Factors of {0} : {1} {2} - {3}",

number, factor1, factor2, answer);

}



public static void Main()

{

DemonstrateAsyncPattern demonstrator = new DemonstrateAsyncPattern();

demonstrator.FactorizeNumberUsingCallback();

demonstrator.FactorizeNumberAndWait();

}

}



}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: