2010-04-26 34 views
6

Tôi muốn sử dụng số WebClient (hoặc có một lựa chọn tốt hơn?) Nhưng có vấn đề. Tôi hiểu rằng việc mở luồng sẽ mất một thời gian và điều này không thể tránh được. Tuy nhiên, việc đọc nó mất nhiều thời gian hơn rất nhiều so với việc đọc nó hoàn toàn ngay lập tức.Làm cách nào để tải tệp xuống chuỗi có gọi lại tiến trình?

Có cách nào tốt nhất để thực hiện việc này không? Tôi có nghĩa là hai cách, để chuỗi và để tập tin. Progress là đại biểu của riêng tôi và nó hoạt động tốt.


FIFTH UPDATE:

Cuối cùng, tôi cố gắng làm điều đó. Trong khi chờ đợi, tôi đã kiểm tra một số giải pháp khiến tôi nhận ra rằng vấn đề nằm ở nơi khác.

Tôi đã thử nghiệm các đối tượng tùy chỉnh WebResponseWebRequest, thư viện libCURL.NET và thậm chí Sockets.

Sự khác biệt về thời gian là nén gzip. Chiều dài luồng nén chỉ đơn giản là một nửa chiều dài luồng thông thường và do đó thời gian tải xuống dưới 3 giây với trình duyệt.

tôi đặt một số mã nếu ai đó sẽ muốn biết làm thế nào tôi giải quyết thế này: (một số tiêu đề không cần thiết)

public static string DownloadString(string URL) 
    { 
     WebClient client = new WebClient(); 
     client.Headers["User-Agent"] = "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/532.5 (KHTML, like Gecko) Chrome/4.1.249.1045 Safari/532.5"; 
     client.Headers["Accept"] = "application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5"; 
     client.Headers["Accept-Encoding"] = "gzip,deflate,sdch"; 
     client.Headers["Accept-Charset"] = "ISO-8859-2,utf-8;q=0.7,*;q=0.3"; 

     Stream inputStream = client.OpenRead(new Uri(URL)); 
     MemoryStream memoryStream = new MemoryStream(); 
     const int size = 32 * 4096; 
     byte[] buffer = new byte[size]; 

     if (client.ResponseHeaders["Content-Encoding"] == "gzip") 
     { 
      inputStream = new GZipStream(inputStream, CompressionMode.Decompress); 
     } 

     int count = 0; 
     do 
     { 
      count = inputStream.Read(buffer, 0, size); 
      if (count > 0) 
      { 
       memoryStream.Write(buffer, 0, count); 
      } 
     } 
     while (count > 0); 

     string result = Encoding.Default.GetString(memoryStream.ToArray()); 
     memoryStream.Close(); 
     inputStream.Close(); 
     return result; 
    } 

Tôi nghĩ rằng chức năng asyncro sẽ gần như giống nhau. Nhưng tôi sẽ chỉ sử dụng một sợi khác để kích hoạt chức năng này. Tôi không cần chỉ dẫn tiến trình percise.

+0

Chính xác thì điều gì không tốt? Chuỗi bạn viết ở đâu? – Marcel

+0

Kết quả không tốt bởi vì nó chỉ là 2048 (iSize) ký tự từ cuối tập tin. Và nó rất chậm chạp để tải xuống tất cả. – Kaminari

+0

Bạn dường như đang đọc cùng một luồng 'Stream' ở hai nơi; 'reader' và' streamRemote' ... Tôi đang bối rối ... Ngoài ra; xem ra: khi xử lý byte, bạn không phải lúc nào cũng đọc các khối ('iByteSize') là toàn bộ số ký tự. Nó cũng không phải là rất rõ ràng như thế nào các bản cập nhật giao diện người dùng xảy ra trong cuộc gọi lại; nếu điều này liên quan đến một chuyển đổi luồng sẽ thêm sự chậm trễ (như các 'DoEvents' bị nguyền rủa). –

Trả lời

1

Bạn chỉ nhận được iSize byte cuối cùng từ tệp của mình vì bạn ghi đè bộ đệm của mình trên mỗi lần lặp, bạn không lưu bộ đệm ở bất kỳ đâu. Đây là một ví dụ về cách lưu trữ tệp trong bộ nhớ bằng cách sử dụng MemoryStream.

var totalBytes = new MemoryStream(1024 * 1024); 
while ((iByteSize = streamRemote.Read(byteBuffer, 0, iByteSize)) > 0) 
{ 
    totalBytes.Write(byteBuffer, 0, iByteSize); 
    iRunningByteTotal += iByteSize; 

    //Some progress calculation 
    if (Progress != null) Progress(iProgressPercentage); 
} 

Khi toàn bộ quá trình tải xuống hoàn tất, bạn có thể chuyển đổi thành văn bản.

var byteArray = totalBytes.GetBuffer(); 
var numberOfBytes = totalBytes.Length; 
var text = Encoding.Default.GetString(byteArray, 0, numberOfBytes); 

Cập nhật: phương pháp DownloadStringAsync cơ bản nào tương tự như trên, nhưng sẽ không cung cấp cho bạn bất kỳ dấu hiệu tiến bộ. Có một số phương pháp không đồng bộ khác mặc dù sẽ kích hoạt sự kiện DownloadProgressChanged.

Cập nhật 2: Về thời gian phản hồi. Bạn đã định thời gian tải xuống tài nguyên bằng một số công cụ khác chưa? Các trình duyệt chính đã xây dựng hỗ trợ cho việc định thời gian như vậy.

Hơn nữa, đây có phải là tệp tĩnh mà bạn phân phát hoặc là nội dung được tạo trên máy chủ không?

Điều thứ ba xuất hiện trong đầu là đệm bên trong. Ví dụ. nếu thuộc tính Response.Buffer trong ASP.Net được sử dụng, không có gì sẽ được gửi đến máy khách cho đến khi toàn bộ tệp/trang được thực hiện serverside. Vì vậy, khách hàng sẽ phải đợi trước khi nó có thể bắt đầu tải xuống.

+0

Trình duyệt tải toàn bộ trang trong khoảng 5 giây. Tải xuống chuỗi Tốc độ không đồng bộ là như nhau. Nhưng kỳ lạ tôi nhận được một số tiến bộ 0 và 100 cuối cùng. Nó không phải là async như tôi nghĩ rằng nó sẽ được. – Kaminari

+0

@Kaminari - chúng ta đang nói về các tệp lớn như thế nào? nếu chúng nhỏ, có lẽ sẽ hiệu quả hơn để phục vụ bạn cùng một lúc, thay vì cắt nhỏ phần tải xuống thành từng phần nhỏ. –

+0

@Peter Lillevold nó không phải là một tập tin. Đó là một trang web. Nhưng chỉ html mà không có các yếu tố khác. Kích thước khoảng 1,33MB. – Kaminari

1

Tôi rất bối rối bởi đúp đọc, nhưng nó trông như bạn thực sự có ý định làm điều gì đó như:

 StringBuilder sb = new StringBuilder();   
     using (StreamReader reader = new StreamReader(streamRemote)) 
     { 
      char[] charBuffer = new char[bufferSize]; 
      int charsRead; 
      while ((charsRead = reader.Read(charBuffer, 0, bufferSize)) > 0) 
      { 
       sb.Append(charBuffer, 0, charsRead); 
       //Some progress calculation 

       if (Progress != null) Progress(iProgressPercentage); 
      } 
     } 
     string result = sb.ToString(); 

Xem nếu mà làm việc như mong muốn .. Tôi tự hỏi, tuy nhiên, nếu các Progress không phải là nguyên nhân của sự sụt giảm; hãy thử nó mà không có điều này được giao, xem nếu điều đó làm cho nó nhanh hơn. Hoặc chỉ chạy theo định kỳ này:

  //[snip] 
      int iteration = 0, charsRead; 
      while ((charsRead = reader.Read(charBuffer, 0, bufferSize)) > 0) 
      { 
       sb.Append(charBuffer, 0, charsRead); 
       //Some progress calculation 
       if((++iteration % 20) == 0 && Progress != null) { 
        Progress(iProgressPercentage); 
       } 
      } 
      //[snip] 

Ngoài ra, hãy thử tăng kích thước bộ đệm.

+0

Nhưng tại sao luồng mở lại có cùng lượng thời gian như trình duyệt web tải xuống toàn bộ trang? – Kaminari

Các vấn đề liên quan