异步获取远程二进制数据

本文介绍了一种使用C#实现的异步获取远程二进制数据的方法,包括图片预览URL获取及指定范围内的数据下载。通过创建自定义的状态对象和使用HTTP请求的BeginGetResponse方法来实现异步数据读取。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

using System;
using System.Net;
using System.Threading;
using System.Text;
using System.IO;
using System.Drawing;
/*
 * 异步获取远程二进制数据
 * 王保宏 2006-2-28
 * */
namespace RDP
{
 // RequestState 类用于通过
 // 异步调用传递数据
 public class RequestState
 {
  const int BUFFER_SIZE = 1024*32;
  //public byte[] RequestData;
  public byte[] BufferRead;
  
  public HttpWebRequest Request;
  public Stream ResponseStream;
  public System.IO.MemoryStream str;
  

  public RequestState()
  {
   BufferRead = new byte[BUFFER_SIZE];
   //RequestData = new byte[BUFFER_SIZE];
   Request = null;
   ResponseStream = null;
  }
 }

 // ClientGetAsync 发出异步请求
 public class ClientGetAsync
 {
  public static ManualResetEvent allDone = new ManualResetEvent(false);
  const int BUFFER_SIZE = 1024*32;

  public static Bitmap GetPreviewUrl(string Url)
  {
   Url=RDP.Xml.ReplaceUrl(Url);
   try
   {
    
    // 创建请求对象
    HttpWebRequest wreq = (HttpWebRequest) WebRequest.Create(Url);
    wreq=RDP.Xml.CMWAP(wreq);

    // 创建状态对象
    RequestState rs = new RequestState();

    // 将请求添加到状态,以便它可以被来回传递
    rs.Request = wreq;

    // 发出异步请求
    IAsyncResult r = (IAsyncResult) wreq.BeginGetResponse(new AsyncCallback(RespCallback), rs);

    rs.str=new MemoryStream();

    // 将 ManualResetEvent 设置为 Wait,
    // 以便在调用回调前,应用程序不退出
    allDone.WaitOne();
    
    Bitmap bitmap = new Bitmap(rs.str);
    
    rs.str.Close();
    allDone.Reset();
    
    return bitmap;
    
   }
   catch(Exception ex)
   {
    throw ex;
   }

  }

  public  static MemoryStream GetBinary_Down(string Url,int start,int end)
  {
   Url=RDP.Xml.ReplaceUrl(Url);

   try
   {
    // 创建请求对象
    HttpWebRequest wreq = (HttpWebRequest) WebRequest.Create(Url);
   
    wreq.AddRange(start,end);
    wreq=RDP.Xml.CMWAP(wreq);

    // 创建状态对象
    RequestState rs = new RequestState();

    // 将请求添加到状态,以便它可以被来回传递
    rs.Request = wreq;

    // 发出异步请求
    IAsyncResult r = (IAsyncResult) wreq.BeginGetResponse(new AsyncCallback(RespCallback), rs);

    rs.str=new MemoryStream();

    // 将 ManualResetEvent 设置为 Wait,
    // 以便在调用回调前,应用程序不退出
    allDone.WaitOne();

  
    allDone.Reset();
    return rs.str;

    
    
   }
   catch(Exception ex)
   {
    throw ex;
   }

  }
  

  private static void RespCallback(IAsyncResult ar)
  {
   // 从异步结果获取 RequestState 对象
   RequestState rs = (RequestState) ar.AsyncState;

   // 从 RequestState 获取 HttpWebRequest
   HttpWebRequest req = rs.Request;

   // 调用 EndGetResponse 生成 HttpWebResponse 对象
   // 该对象来自上面发出的请求
   HttpWebResponse resp = (HttpWebResponse) req.EndGetResponse(ar);

   // 既然我们拥有了响应,就该从
   // 响应流开始读取数据了
   Stream ResponseStream = resp.GetResponseStream();

   // 该读取操作也使用异步完成,所以我们
   // 将要以 RequestState 存储流
   rs.ResponseStream = ResponseStream;

   // 请注意,rs.BufferRead 被传入到 BeginRead。
   // 这是数据将被读入的位置。
   IAsyncResult iarRead = ResponseStream.BeginRead(rs.BufferRead, 0, BUFFER_SIZE, new AsyncCallback(ReadCallBack), rs);
  }


  private static void ReadCallBack(IAsyncResult asyncResult)
  {
   // 从 asyncresult 获取 RequestState 对象
   RequestState rs = (RequestState)asyncResult.AsyncState;


   // 取出在 RespCallback 中设置的 ResponseStream
   Stream responseStream = rs.ResponseStream;
   
   // 此时 rs.BufferRead 中应该有一些数据。
   // 读取操作将告诉我们那里是否有数据
   int read = responseStream.EndRead( asyncResult );


   if (read > 0)
   {
    //rs.fs.Write(rs.BufferRead,0,read);
    rs.str.Write(rs.BufferRead,0,read);

   
    // 现在发出另一个异步调用,读取更多的数据
    // 请注意,将不断调用此过程,直到
    // responseStream.EndRead 返回 -1
    IAsyncResult ar = responseStream.BeginRead( rs.BufferRead, 0, BUFFER_SIZE, new AsyncCallback(ReadCallBack), rs);
   }
   else
   {
    //rs.fs.Close();
    //rs.str.Close();
    rs=null;
    // 关闭响应流
    responseStream.Close();
    // 设置 ManualResetEvent,以便主线程可以退出
    allDone.Set();
  
    System.GC.WaitForPendingFinalizers();
    System.GC.Collect();
    
   }
   return;
  }
 }

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值