使用异步方式调用同步方法
来源:互联网 发布:证件照扫描软件 编辑:程序博客网 时间:2024/05/21 17:54
转载:http://msdn.microsoft.com/zh-cn/library/2e08f6yc(v=vs.80).aspx
.NET Framework 允许您异步调用任何方法。为此,应定义与您要调用的方法具有相同签名的委托;公共语言运行库会自动使用适当的签名为该委托定义 BeginInvoke 和 EndInvoke 方法。
BeginInvoke 方法可启动异步调用。它与您需要异步执行的方法具有相同的参数,另外它还有两个可选参数。第一个参数是一个AsyncCallback 委托,该委托引用在异步调用完成时要调用的方法。第二个参数是一个用户定义的对象,该对象可向回调方法传递信息。BeginInvoke 立即返回,不等待异步调用完成。BeginInvoke 会返回IAsyncResult,这个结果可用于监视异步调用进度。
EndInvoke 方法检索异步调用的结果。调用 BeginInvoke 后可随时调用 EndInvoke 方法;如果异步调用尚未完成,EndInvoke 将一直阻止调用线程,直到异步调用完成后才允许调用线程执行。EndInvoke 的参数包括您需要异步执行的方法的out 和 ref 参数(在 Visual Basic 中为 <Out> ByRef 和 ByRef)以及由 BeginInvoke 返回的 IAsyncResult。
本主题中的代码示例演示了四种使用 BeginInvoke 和 EndInvoke 进行异步调用的常用方法。调用 BeginInvoke 之后,您可以执行下列操作:
进行某些操作,然后调用 EndInvoke 一直阻止到调用完成。
使用 System.IAsyncResult.AsyncWaitHandle 属性获取 WaitHandle,使用它的 WaitOne 方法一直阻止执行直到发出 WaitHandle 信号,然后调用 EndInvoke。
轮询由 BeginInvoke 返回的 IAsyncResult,确定异步调用何时完成,然后调用 EndInvoke。
将用于回调方法的委托传递给 BeginInvoke。异步调用完成后,将在 ThreadPool 线程上执行该方法。该回调方法将调用 EndInvoke。
定义测试方法和异步委托
下面的代码示例演示异步调用同一个长时间运行的方法 TestMethod 的各种方式。TestMethod 方法会显示一条控制台消息,说明它已开始处理,休眠了几秒钟,然后结束。TestMethod 有一个out 参数,该参数用于演示此种参数添加到 BeginInvoke 和 EndInvoke 的签名中的方式。您可以按同样的方式处理ref 参数。
下面的代码示例演示 TestMethod 的定义和名为 AsyncMethodCaller 的、可用来异步调用 TestMethod 的委托。若要编译任何代码示例,必须包括 TestMethod 的定义和 AsyncMethodCaller 委托。
using System;
using System.Threading;
namespace Examples.AdvancedProgramming.AsynchronousOperations
{
public class AsyncMain
{
public static void Main()
{
// The asynchronous method puts the thread id here.
int threadId;
// Create an instance of the test class.
AsyncDemo ad = new AsyncDemo();
// Create the delegate.
AsyncMethodCaller caller = new AsyncMethodCaller(ad.TestMethod);
// Initiate the asychronous call.
IAsyncResult result = caller.BeginInvoke(3000,
out threadId, null, null);
Thread.Sleep(0);
Console.WriteLine("Main thread {0} does some work.",
Thread.CurrentThread.ManagedThreadId);
// Call EndInvoke to wait for the asynchronous call to complete,
// and to retrieve the results.
string returnValue = caller.EndInvoke(out threadId, result);
Console.WriteLine("The call executed on thread {0}, with return value \"{1}\".",
threadId, returnValue);
}
}
}
使用 WaitHandle 等待异步调用
您可以使用 BeginInvoke 返回的 IAsyncResult 的 AsyncWaitHandle 属性来获取WaitHandle。异步调用完成时会发出 WaitHandle 信号,而您可以通过调用 WaitOne 方法等待它。如果您使用 WaitHandle,则在异步调用完成之前或之后,在通过调用 EndInvoke 检索结果之前,还可以执行其他处理。
using System;
using System.Threading;
namespace Examples.AdvancedProgramming.AsynchronousOperations
{
public class AsyncMain
{
static void Main()
{
// The asynchronous method puts the thread id here.
int threadId;
// Create an instance of the test class.
AsyncDemo ad = new AsyncDemo();
// Create the delegate.
AsyncMethodCaller caller = new AsyncMethodCaller(ad.TestMethod);
// Initiate the asychronous call.
IAsyncResult result = caller.BeginInvoke(3000,
out threadId, null, null);
Thread.Sleep(0);
Console.WriteLine("Main thread {0} does some work.",
Thread.CurrentThread.ManagedThreadId);
// Wait for the WaitHandle to become signaled.
result.AsyncWaitHandle.WaitOne();
// Perform additional processing here.
// Call EndInvoke to retrieve the results.
string returnValue = caller.EndInvoke(out threadId, result);
Console.WriteLine("The call executed on thread {0}, with return value \"{1}\".",
threadId, returnValue);
}
}
}
轮询异步调用完成
您可以使用由 BeginInvoke 返回的 IAsyncResult 的 IsCompleted 属性来发现异步调用何时完成。从用户界面的服务线程中进行异步调用时可以执行此操作。轮询完成允许调用线程在异步调用在 ThreadPool 线程上执行时继续执行。
using System;
using System.Threading;
namespace Examples.AdvancedProgramming.AsynchronousOperations
{
public class AsyncMain
{
static void Main() {
// The asynchronous method puts the thread id here.
int threadId;
// Create an instance of the test class.
AsyncDemo ad = new AsyncDemo();
// Create the delegate.
AsyncMethodCaller caller = new AsyncMethodCaller(ad.TestMethod);
// Initiate the asychronous call.
IAsyncResult result = caller.BeginInvoke(3000,
out threadId, null, null);
// Poll while simulating work.
while(result.IsCompleted == false) {
Thread.Sleep(10);
}
// Call EndInvoke to retrieve the results.
string returnValue = caller.EndInvoke(out threadId, result);
Console.WriteLine("The call executed on thread {0}, with return value \"{1}\".",
threadId, returnValue);
}
}
}
异步调用完成时执行回调方法
如果启动异步调用的线程不需要是处理结果的线程,则可以在调用完成时执行回调方法。回调方法在 ThreadPool 线程上执行。
若要使用回调方法,必须将引用回调方法的 AsyncCallback 委托传递给 BeginInvoke。也可以传递包含回调方法将要使用的信息的对象。例如,可以传递启动调用时曾使用的委托,以便回调方法能够调用 EndInvoke。
using System;
using System.Threading;
namespace Examples.AdvancedProgramming.AsynchronousOperations
{
public class AsyncMain
{
// Asynchronous method puts the thread id here.
private static int threadId;
static void Main() {
// Create an instance of the test class.
AsyncDemo ad = new AsyncDemo();
// Create the delegate.
AsyncMethodCaller caller = new AsyncMethodCaller(ad.TestMethod);
// Initiate the asychronous call. Include an AsyncCallback
// delegate representing the callback method, and the data
// needed to call EndInvoke.
IAsyncResult result = caller.BeginInvoke(3000,
out threadId,
new AsyncCallback(CallbackMethod),
caller );
Console.WriteLine("Press Enter to close application.");
Console.ReadLine();
}
// Callback method must have the same signature as the
// AsyncCallback delegate.
static void CallbackMethod(IAsyncResult ar)
{
// Retrieve the delegate.
AsyncMethodCaller caller = (AsyncMethodCaller) ar.AsyncState;
// Call EndInvoke to retrieve the results.
string returnValue = caller.EndInvoke(out threadId, ar);
Console.WriteLine("The call executed on thread {0}, with return value \"{1}\".",
threadId, returnValue);
}
}
}
- 使用异步方式调用同步方法
- 使用异步方式调用同步方法
- 使用异步方式调用同步方法
- 使用异步方式调用同步方法
- 使用异步方式调用WebService
- Android 异步方法以同步方式进行
- DWR的同步和异步使用方式
- dubbo异步同步调用混合使用问题
- 同步调用、异步调用
- VC++ .NET UI同步(使用Invoke托管方法),异步线程调用UI
- ExtJs异步ajax调用和同步ajax调用公用方法
- dubbo使用异步方式调用对象
- 同步和异步调用
- ajax同步异步调用
- 异步调用同步返回
- 同步调用和异步调用
- 同步调用和异步调用
- 同步调用 回调 异步调用
- g723源码详细分析(-)
- 轻松修改网卡的MAC(物理)地址
- linux下scp命令详解
- Active x 漏洞挖掘与分析
- ASP.NET服务器验证控件和JS自定义验证同时使用(小技巧)
- 使用异步方式调用同步方法
- 如何通过phonegap安卓插件实现复制(到剪贴板)黏贴操作
- 秋雨寄相思
- 数字图像处理的基本原理和常用方法
- 关于网站流量的监控
- PAZU打印控件-浏览器无提示打印解决方案
- TCP时延问题
- scoped_ptr analysis
- 2.16 求数组中最长的递增子序列