C#同步方法和异步方法的区别

  • 格式:pdf
  • 大小:222.51 KB
  • 文档页数:14
// 将请求添加到状态,以便它可以被来回传递 rs.Request = wreq;
// 发出异步请求 IAsyncResult r = (IAsyncResult)wreq.BeginGetResponse(new AsyncCallbac k(RespCallback), rs);
// 将 ManualResetEvent 设置为 Wait, // 以便在调用回调前,应用程序不退出 allDone.WaitOne(); }
}
2)下面看有回调函数的 WebRequest WebResponse 的异步操作。
using System; using ; using System.Threading; using System.Text; using System.IO;
// RequestState 类用于通过 // 异步调用传递数据 public class RequestState {
private static void ReadCallBack(IAsyncResult asyncResult) {
// 从 asyncresult 获取 RequestState 对象 RequestState rs = (RequestState)asyncResult.AsyncState;
const int BUFFER_SIZE = 1024; public StringBuilder RequestData; public byte[] BufferRead; public HttpWebRequest Request; public Stream ResponseStream; // 创建适当编码类型的解码器 public Decoder StreamDecode = Encoding.UTF8.GetDecoder();
// 该读取操作也使用异步完成,所以我们 // 将要以 RequestState 存储流 rs.ResponseStream = ResponseStream;
// 请注意,rs.BufferRead 被传入到 BeginRead。 // 这是数据将被读入的位置。 IAsyncResult iarRead = ResponseStream.BeginRead(rs.BufferRead, 0, BUF FER_SIZE, new AsyncCallback(ReadCallBack), rs); }
i=i+1; Console.WriteLine("Event2 "+i.ToString()); } Console.WriteLine("Event2 End"); }
[STAThread] static void Main(string[] args) {
long start=0; long end=0; Class1 c = new Class1(); Console.WriteLine("ready"); start=DateTime.Now.Ticks;
System.Threading.Thread.Sleep(4000); Console.WriteLine("Event1 End"); }
// 同步方法 void Event2() {
Console.WriteLine("Event2 Start"); int i=1; while(i<1000) {
// 调用 EndGetResponse 生成 HttpWebResponse 对象
// 该对象来自上面发出的请求 HttpWebResponse resp = (HttpWebResponse)req.EndGetResponse(ar);
// 既然我们拥有了响应,就该从 // 响应流开始读取数据了 Stream ResponseStream = resp.GetResponseStream();
同步方法和异步方法的区别
同步方法调用在程序继续执行之前需要等待同步方法执行完毕返回结果 异步方法则在被调用之后立即返回以便程序在被调用方法完成其任务的同 时执行其它操作 林 sir 提 示 :在 异 步 方 法 里 面 , 注 意 的 是 回 调 函 数 ! 搞 定 了 回 调 函 数 就 基 本 了解异步编程。
换回调函数里面 IAsyncResult.AsyncState(BeginInvoke 方法的最后一个参数)成委托,然 后用委托执行 EndInvoke。 警告 始终在异步调用完成后调用 EndInvoke。
以上有不理解的稍后可以再理解。
例子
1)先来个简单的没有回调函数的异步方法例子 请再运行程序的时候,仔细看注释,对理解很有帮助。还有,若将注释的中的两个方法都同 步,你会发现异步运行的速度优越性。
// 取出在 RespCallback 中设置的 ResponseStream Stream responseStream = rs.ResponseStream;
// 此时 rs.BufferRead 中应该有一些数据。 // 读取操作将告诉我们那里是否有数据 int read = responseStream.EndRead(asyncResult);
BeginInvoke 立即返回,不等待异步调用完成。 BeginInvoke 返回 IasyncResult,可用于监视调用进度。
EndInvoke 方法用于检索异步调用结果。调用 BeginInvoke 后可随时调用 EndInvoke 方 法;如果异步调用未完成,EndInvoke 将一直阻塞到
showusage(); return;
}
// 从命令行获取 URI Uri HttpSite = new Uri(args[0]);
// 创建请求对象 HttpWebRequest wreq = (HttpWebRequest)WebRequest.Create(HttpSite);
// 创建状态对象 RequestState rs = new RequestState();
using System;
namespace ConsoleApplication1 {
class Class1 {
//声明委托 public delegate void AsyncEventHandler();
//异步方法 void Event1() {
Console.WriteLine("Event1 Start");
public RequestState()
{ BufferRead = new byte[BUFFER_SIZE]; RequestData = new StringBuilder(""); Request = null; ResponseStream = null;
} }
// ClientGetAsync 发出异步请求 class ClientGetAsync {
public static ManualResetEvent allDone = new ManualResetEvent(false); const int BUFFER_SIZE = 1024;
public static void Main(string[] args) {
if (args.Length < 1) {
异步编程概览
.NET Framework 允许您异步调用任何方法。定义与您需要调用的方法具有相同签名的委托; 公共语言运行库将自动为该委托定义具有适当签名
的 BeginInvoke 和 EndInvoke 方法。
BeginInvoke 方法用于启动异步调用。它与您需要异步执行的方法具有相同的参数,只不过 还有两个额外的参数(将在稍后描述)。
1.进行某些操作,然后调用 EndInvoke 一直阻塞到调用完成。 2.使用 IAsyncResult.AsyncWaitHandle 获取 WaitHandle,使用它的 WaitOne 方法将执行 一直阻塞到发出 WaitHandle 信号,然后调用
EndInvoke。这里主要是主程序等待异步方法,等待异步方法的结果。 3.轮询由 BeginInvoke 返回的 IAsyncResult,IAsyncResult.IsCompeted 确定异步调用何 时完成,然后调用 EndInvoke。此处理个人认为与 相同。 4.将用于回调方法的委托传递给 BeginInvoke。该方法在异步调用完成后在 ThreadPool 线 程上执行,它可以调用 EndInvoke。这是在强制装
String str = new String(charBuffer, 0, len);
// 将最近读取的数据追加到 RequestData stringbuilder 对象中, // 该对象包含在 RequestState 中 rs.RequestData.Append(str);
} }
asy.EndInvoke(ia);
//都同步的情况。 //c.Event1(); //c.Event2();
end =DateTime.Now.Ticks; Console.WriteLine("时间刻度差="+ Convert.ToString(end-start) ); Console.ReadLine();
if (read > 0) {
// 准备 Char 数组缓冲区,用于向 Unicode 转换 Char[] charBuffer = new Char[BUFFER_SIZE];
ffer, 0);
// 将字节流转换为 Char 数组,然后转换为字符串 // len 显示多少字符被转换为 Unicode int len = rs.StreamDecode.GetChars(rs.BufferRead, 0, read, charBu