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();
}
}
}
如果我们想调用一个这样的方法,当调用之后就立即返回,假如在调用期间发生了异常,我们可以在稍后的时间重起该方法的动作。那我们就可以利用异步委托来把我们的方法做成异步的调用。
每个委托都有三个方法: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();
}
}
}
相关文章推荐
- 通过代码学习C#&.NET——委托基础
- C#委托的异步调用[学习]
- 通过代码学习C#&.NET——委托使用(正则表达式替换)
- [深入学习C#]完成异步委托的三种方式
- 通过代码学习C#&.NET——委托使用(通用类设计)
- 通过代码学习C#&.NET——委托使用(线程、任务)
- C#实现异步编程的两个简单机制(异步委托&定时器)及Thread实现多线程
- C#学习系列之委托的异步调用
- 通过代码学习C#&.NET——委托使用(通用类设计)
- [Unity&C#&事件委托]对委托事件的学习与实践
- UI学习 第九章 委托(代理)设计模式      单例设计模式
- 今日学习:关于C#多线程之一——异步委托
- [深入学习C#]完成异步委托的三种方式
- AMP 学习2 图像灰度,c#比c++ amp快?
- 黑马程序员_学习日记66_716ASP.NET(使用回调函数的异步委托、生产者消费者)
- 详细教程C#中的委托和事件应用 一
- C#基础之“.NET研究”委托异步
- MVC&WebForm对照学习:ajax异步请求
- C#委托,事件最初浅的和最易看懂的学习笔记
- C#中的委托和事件(转载学习)