博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[转摘]使用异步方式调用同步方法
阅读量:6200 次
发布时间:2019-06-21

本文共 7495 字,大约阅读时间需要 24 分钟。

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

  • .NET Framework 3.5

 

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

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

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

Note注意

Visual Studio 2005 中的 IntelliSense 功能显示 BeginInvoke 和 EndInvoke 的参数。如果您没有使用 Visual Studio 或类似工具,或您使用的是带有 Visual Studio 2005 的 C#,请参见以获取为这些方法定义的参数的说明。

本主题中的代码示例演示了四种使用 BeginInvoke 和 EndInvoke 进行异步调用的常用方法。调用 BeginInvoke 之后,您可以执行下列操作:

  • 进行某些操作,然后调用 EndInvoke 一直阻止到调用完成。

  • 使用 属性获取 ,使用它的 方法一直阻止执行直到发出 WaitHandle 信号,然后调用 EndInvoke。

  • 轮询由 BeginInvoke 返回的 IAsyncResult,确定异步调用何时完成,然后调用 EndInvoke。

  • 将用于回调方法的委托传递给 BeginInvoke。异步调用完成后,将在 线程上执行该方法。该回调方法将调用 EndInvoke。

    Note要点

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

 

 

定义测试方法和异步委托

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

下面的代码示例演示 TestMethod 的定义和名为 AsyncMethodCaller 的、可用来异步调用 TestMethod 的委托。若要编译任何代码示例,必须包括 TestMethod 的定义和 AsyncMethodCaller 委托。

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

 

 

1、使用 EndInvoke 等待异步调用

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

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

 

 

2、使用 WaitHandle 等待异步调用

您可以使用 BeginInvoke 返回的 IAsyncResultAsyncWaitHandle 属性来获取 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);        }    }}

 

 

3、轮询异步调用完成

您可以使用由 BeginInvoke 返回的 IAsyncResult 的 属性来发现异步调用何时完成。从用户界面的服务线程中进行异步调用时可以执行此操作。轮询完成允许调用线程在异步调用在 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);        }    }}

 

4、异步调用完成时执行回调方法

如果启动异步调用的线程不需要是处理结果的线程,则可以在调用完成时执行回调方法。回调方法在 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);        }    }}

 

原文地址:

转载地址:http://uttca.baihongyu.com/

你可能感兴趣的文章
GBDT学习
查看>>
tp3.2 复合查询or
查看>>
spoj1716 Can you answer these queries III
查看>>
数据库进阶
查看>>
英语学习/词典App分析-团队作业(五)
查看>>
C. Polycarpus' Dice Codeforces Round #298 (Div. 2)
查看>>
NoSql Cassandra
查看>>
地理坐标系与投影坐标系的区别
查看>>
转:ASP.NET基于角色的窗体安全认证机制
查看>>
Git 分支管理
查看>>
远程SSH连接服务与基本排错
查看>>
Spring Boot 整合 Elasticsearch,实现 function score query 权重分查询
查看>>
重写ResultSet实现分页功能(最好的分页技术)(转)
查看>>
KMP算法的Next数组详解(转)
查看>>
用Vim搭建C/C++开发环境
查看>>
关于box-shadow和drop-shadow的显著区别
查看>>
POJ 刷题进程.2
查看>>
安装php xdebug扩展
查看>>
[PHP] 算法-二叉树的子结构判断的PHP实现
查看>>
python re.sub
查看>>