[英]Async method doesn't work as expected
I am making test console app that is to download streaming mp4 using URL. 我正在制作测试控制台应用程序,该应用程序将使用URL下载流mp4。
I used async example posted on MSDN. 我使用了MSDN上发布的异步示例。
Below is the code. 下面是代码。
class Program
{
public static ManualResetEvent allDone = new ManualResetEvent(false);
const int BUFFER_SIZE = 1024;
public static int total = 0;
static void Main(string[] args)
{
Uri httpSite = new Uri("URI");
WebRequest wreq = WebRequest.Create(httpSite);
RequestState rs = new RequestState();
rs.Request = wreq;
IAsyncResult r = (IAsyncResult)wreq.BeginGetResponse(
new AsyncCallback(RespCallback), rs);
allDone.WaitOne();
FileStream file = new FileStream("test.mp4", FileMode.Append);
file.Write(rs.data.ToArray(), 0, rs.data.Count());
Console.ReadKey();
}
private static void RespCallback(IAsyncResult ar)
{
// Get the RequestState object from the async result.
RequestState rs = (RequestState)ar.AsyncState;
// Get the WebRequest from RequestState.
WebRequest req = rs.Request;
// Call EndGetResponse, which produces the WebResponse object
// that came from the request issued above.
WebResponse resp = req.EndGetResponse(ar);
// Start reading data from the response stream.
Stream ResponseStream = resp.GetResponseStream();
// Store the response stream in RequestState to read
// the stream asynchronously.
rs.ResponseStream = ResponseStream;
// Pass rs.BufferRead to BeginRead. Read data into rs.BufferRead
IAsyncResult iarRead = ResponseStream.BeginRead(rs.BufferRead, 0,
BUFFER_SIZE, new AsyncCallback(ReadCallBack), rs);
}
private static void ReadCallBack(IAsyncResult asyncResult)
{
// Get the RequestState object from AsyncResult.
RequestState rs = (RequestState)asyncResult.AsyncState;
// Retrieve the ResponseStream that was set in RespCallback.
Stream responseStream = rs.ResponseStream;
// Read rs.BufferRead to verify that it contains data.
int read = responseStream.EndRead(asyncResult);
if (read > 0)
{
// Prepare a Char array buffer for converting to Unicode.
byte[] charBuffer = new byte[BUFFER_SIZE];
responseStream.Read(charBuffer, 0, read);
rs.data.AddRange(charBuffer);
IAsyncResult ar = responseStream.BeginRead(
rs.BufferRead, 0, BUFFER_SIZE,
new AsyncCallback(ReadCallBack), rs);
}
else
{
responseStream.Close();
// Set the ManualResetEvent so the main thread can exit.
allDone.Set();
}
return;
}
}
When I used this async method the saved file size is 1,356KB whele the file is suppoed to be 2,409KB. 当我使用这种异步方法时,保存的文件大小为1356KB,而该文件的大小应为2409KB。
I could find the breakpoint in IF(read > 0) statement was hit after the breakpoint on responseStream.close() was hit. 在responseStream.close()上的断点被击中之后,我可以在IF(read> 0)语句中找到断点。 Is this because it read 0 length and read more after then?
这是因为它读取0长度,然后读取更多吗?
When I used non-async method like below, I could successfully download the file. 当我使用如下所示的非异步方法时,我可以成功下载文件。
public static void StreamDownload(string url)
{
int dataLength;
int bytesRead;
WebRequest req = WebRequest.Create(url);
WebResponse response = req.GetResponse();
string fileName = System.IO.Path.GetFileName("test.mp4");
Stream dataStream = response.GetResponseStream();
byte[] buffer = new byte[1024];
FileStream file = new FileStream(fileName, FileMode.Append);
dataLength = (int)response.ContentLength;
do
{
bytesRead = dataStream.Read(buffer, 0, buffer.Length);
file.Write(buffer, 0, bytesRead);
} while (bytesRead != 0);
}
Doesn anyone know why I failed with async method? 有谁知道我为什么用异步方法失败了?
Thanks for your help. 谢谢你的帮助。
There are multiple other ways to download a file that are far more simple , you should choose one of them. 有多种其他下载文件的方法,它们更为简单 ,您应该选择其中一种。
webclient vs httpclient vs httpwebrequest webclient vs httpclient vs httpwebrequest
In your case I would suggest HttpClient : 在您的情况下,我建议HttpClient :
public static async Task DownloadAsync(string requestUri, string filename)
{
using (var httpClient = new HttpClient())
{
using (var fs = File.OpenWrite(filename))
{
await (await httpClient.GetStreamAsync(requestUri)).CopyToAsync(fs);
}
}
}
Or you could use the DownloadFileAsync method of the WebClient class, if you need to show some progress, but the example above is simpler. 或者,如果需要显示一些进度,则可以使用WebClient类的DownloadFileAsync方法,但是上面的示例更简单。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.