您的位置:首页 > 其它

使用异步方式调用同步方法

2011-03-03 11:49 686 查看
(查询BeginInvoke 2005MSDN 里相关资料,我复制在这里)

 

.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。

每次都要调用 EndInvoke 来完成异步调用。

定义测试方法和异步委托

下面的代码示例演示异步调用同一个长时间运行的方法
TestMethod

的各种方式。
TestMethod

方法会显示一条控制台消息,说明它已开始处理,休眠了几秒钟,然后结束。
TestMethod
有一个 out
参数,该参数用于演示此种参数添加到 BeginInvoke 和 EndInvoke 的签名中的方式。您可以按同样的方式处理 ref 参数。

下面的代码示例演示
TestMethod
的定义和名为
AsyncMethodCaller

的、可用来异步调用
TestMethod
的委托。若要编译任何代码示例,必须包括
TestMethod

的定义和
AsyncMethodCaller
委托。

I

C# 
using System;
using System.Threading;

namespace Examples.AdvancedProgramming.AsynchronousOperations
{
public class AsyncDemo
{
// The method to be executed asynchronously.
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());
}
}
// The delegate must have the same signature as the method
// it will call asynchronously.
public delegate string AsyncMethodCaller(int callDuration, out int threadId);
}

使用 EndInvoke 等待异步调用

异步执行方法最简单的方式是通过调用委托的 BeginInvoke 方法来开始执行方法,在主线程上执行一些工作,然后调用委托的 EndInvoke
方法。EndInvoke 可能会阻止调用线程,因为它直到异步调用完成之后才返回。这种技术非常适合文件或网络操作,但是由于 EndInvoke
会阻止它,所以不要从服务于用户界面的线程中调用它。

C# 
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 检索结果之前,还可以执行其他处理。

C# 
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 WaitHa
4000
ndle 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
线程上执行时继续执行。

C# 
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。

C# 
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);
}
}
}

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