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

使用委托进行异步编程

2011-04-13 17:41 423 查看
使用委托进行异步编程与异步编程设计模式差不多。可以参考前一篇文章

异步编程设计模式 /article/6924164.html

使用委托进行异步编程

.NET Framework 4

其他版本



使用委托可以通过异步方式调用同步方法。 当同步调用一个委托时,Invoke 方法直接调用对当前线程的目标方法。 如果调用 BeginInvoke 方法,则公共语言运行时 (CLR) 会对请求进行排队并立即返回到调用方。 会对来自线程池的线程异步调用目标方法。 提交请求的原始线程自由地继续与目标方法并行执行。 如果在对 BeginInvoke 方法的调用中指定了回调方法,则当目标方法结束时将调用该回调方法。 在回调方法中,EndInvoke 方法获取返回值和所有输入/输出参数或仅供输出参数。 如果在调用BeginInvoke 时未指定任何回调方法,则可以从调用 BeginInvoke 的线程中调用 EndInvoke。

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

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

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


注意
Visual Studio 2005 中的 IntelliSense 功能显示 BeginInvoke 和 EndInvoke 的参数。如果您没有使用 Visual Studio 或类似工具,或您使用的是带有 Visual Studio 2005 的 C#,请参见异步编程概述以获取为这些方法定义的参数的说明。
class Program
{
static void Main()
{
Action<int, int> action = (x, y) =>
{
for (int i = x; i <= y; i++)
if (IsPrimeNumber(i))
Console.Write(i + ",");
};
Console.WriteLine("synchronous");
action.Invoke(1000, 1500);//synchronous
Console.WriteLine("\nno block");
IAsyncResult result = action.BeginInvoke(1000, 1500, null, null);
Console.WriteLine("\nAsyncWaitHandle.WaitOne()");
IAsyncResult result0 = action.BeginInvoke(1000, 1500, null, null);
result0.AsyncWaitHandle.WaitOne();
Console.WriteLine("\nEndInvoke");
IAsyncResult result1 = action.BeginInvoke(1000, 1500, null, null);
action.EndInvoke(result1);
Console.WriteLine("\nWhile loop");
IAsyncResult result2 = action.BeginInvoke(1000, 1500, null, null);
while (!result2.IsCompleted)//do nothing until it finishes
{
Console.Write(".");
Thread.Sleep(500);
}
Console.WriteLine("\ncall mycallback");
IAsyncResult result3 = action.BeginInvoke(1000, 1500, mycallback, DateTime.Now.ToString("HH:mm:ss:fffffff"));
Thread.Sleep(2000);//guarantee the async callback function works before the main thread finishes
//while (!iresult.IsCompleted)//do nothing until it finishes
//{
// Console.Write(".");
// Thread.Sleep(500);
//}
Console.WriteLine("\nlamuda");
IAsyncResult result4 = action.BeginInvoke(1000, 1500, (r) =>
{
string d = (string)r.AsyncState;
Console.WriteLine("\r\n{0},finished and call mycallback,now:{1}", d, DateTime.Now.ToString("HH:mm:ss:fffffff"));
}, DateTime.Now.ToString("HH:mm:ss:fffffff"));
Thread.Sleep(2000);//guarantee the async callback function works before the main thread finishes
//while (!iresult.IsCompleted)//do nothing until it finishes
//{
// Console.Write(".");
// Thread.Sleep(500);
//}
}
static void mycallback(IAsyncResult result)
{
string d = (string)result.AsyncState;
Console.WriteLine("\r\n{0},finished and call mycallback,now:{1}", d, DateTime.Now.ToString("HH:mm:ss:fffffff"));
}
static bool IsPrimeNumber(int n)
{
bool b = true;
if (n == 1)
b = false;
else if (n == 2)
b = true;
else
{
int sqr = Convert.ToInt32(Math.Sqrt(n));
for (int i = sqr; i >= 2; i--)
{
if (n % i == 0)
{
b = false;
}
}
}
return b;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: