Xamarin - 多个HTTP请求会降低应用程序的速度

时间:2014-05-23 08:15:11

标签: c# ios http xamarin httprequest

我正在使用Xamarin开发iOS应用。其中一个功能是以hls格式下载视频,这意味着每个视频可以有100到1000个块来下载。所以我需要做100到1000个http请求。这是有效但下载时应用程序非常慢,我使用“仪器”进行了性能测试,CPU处于80%,一旦完成,它会回到0%-1%。这是在ipad上测试,而不是在模拟器上测试。

public async Task CreateDownloadTask (string path){

var response = await _httpClient.GetAsync (GetUrl(path),
                                     HttpCompletionOption.ResponseHeadersRead);

if (!response.IsSuccessStatusCode) 
{
    Debug.WriteLine ("Error: " + path);
    RaiseFault(new RpcFault("Error: Unable to download video", -1));
} 
else 
{
    var totalBytes = response.Content.Headers.ContentLength.HasValue 
                   ? response.Content.Headers.ContentLength.Value : -1L;

    using (var stream = await response.Content.ReadAsStreamAsync ()) 
    {
        var isMoreToRead = true;
        var data = new byte[totalBytes];

        do 
        {
            _cancelSource.Token.ThrowIfCancellationRequested ();
            var buffer = new byte[4096];
            int read = stream.ReadAsync(buffer, 
                                        0, 
                                        buffer.Length,
                                        _cancelSource.Token).Result;

            if (read == 0)
                isMoreToRead = false;
            else {
                buffer.ToList ().CopyTo (0, data, receivedBytes, read);
                receivedBytes += read;
                HlsVideo.TotalReceived += read;
            }
        } while(isMoreToRead);

        var fullPath = GetFullFilePath (path);
        _fileStore.WriteFile (fullPath, data);
    }
}

在执行多个http请求时,我该怎么做才能提高性能?

1 个答案:

答案 0 :(得分:2)

目前的代码存在两个问题:

  • 在阅读数据方面效率低下
  • 它同步写入数据,如果你在UI线程
  • ,这显然是个问题

“异步写入数据”可能是一个更简单的修复,所以让我们看一下读取数据的低效率:

  • 您在每次迭代中分配buffer。我们不关心上一次迭代的数据,因此您可以在while循环之前分配一次
  • 您正在ToList上致电buffer,这将打印副本 - 然后您将其复制到data
  • 您根本不需要buffer!您可以直接将直接字节读入data来代替两个分配和两个副本:

    var data = new byte[totalBytes];
    
    do {
        _cancelSource.Token.ThrowIfCancellationRequested ();
        int read = stream.ReadAsync(data, receivedBytes, data.Length - receivedBytes, 
                                    _cancelSource.Token).Result;
    
        receivedBytes += read;
        if (read == 0 || receivedBytes == data.Length)
            isMoreToRead = false;
        }
        HlsVideo.TotalReceived += read;
    } while(isMoreToRead);
    // TODO: check that receivedBytes == data.Length!