1

我有一个应用程序需要在设备上下载和保存文件 - 视频。

视频短约 10 分钟,质量很差,这意味着它们的大小很小。

所以,问题是当我下载一些文件时 - 一切顺利,但有些文件失败并出现错误:内存不足异常。从逻辑上讲,我认为小于某个大小(例如 50MB)的文件可以很好地下载,但更高 - 例外。

这是我的代码:

private void btnDownload2_Click(object sender, RoutedEventArgs e)
    {
        WebClient webClient = new WebClient();
        webClient.DownloadProgressChanged += new DownloadProgressChangedEventHandler(webClient_DownloadProgressChanged);
        webClient.OpenReadCompleted += new OpenReadCompletedEventHandler(webClient_OpenReadCompleted);
        webClient.OpenReadAsync(new Uri("http://somelink/video/nameOfFile.mp4"));
    }

void webClient_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
    {
        try
        {
            if (progressMedia.Value <= progressMedia.Maximum)
            {
                progressMedia.Value = (double)e.ProgressPercentage;
            }

        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
        }
    }

    protected bool IncreaseIsolatedStorageSpace(long quotaSizeDemand)
    {
        bool CanSizeIncrease = false;
        IsolatedStorageFile isolatedStorageFile = IsolatedStorageFile.GetUserStoreForApplication();
        //Get the Available space
        long maxAvailableSpace = isolatedStorageFile.AvailableFreeSpace;
        if (quotaSizeDemand > maxAvailableSpace)
        {
            if (!isolatedStorageFile.IncreaseQuotaTo(isolatedStorageFile.Quota + quotaSizeDemand))
            {
                CanSizeIncrease = false;
                return CanSizeIncrease;
            }
            CanSizeIncrease = true;
            return CanSizeIncrease;
        }
        return CanSizeIncrease;
    }

    void webClient_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
    {
        try
        {
            if (e.Result != null)
            {

                #region Isolated Storage Copy Code
                isolatedStorageFile = IsolatedStorageFile.GetUserStoreForApplication();

                bool checkQuotaIncrease = IncreaseIsolatedStorageSpace(e.Result.Length);

                string VideoFile = "PlayFile.wmv";
                isolatedStorageFileStream = new IsolatedStorageFileStream(VideoFile, FileMode.Create, isolatedStorageFile);
                long VideoFileLength = (long)e.Result.Length;
                byte[] byteImage = new byte[VideoFileLength];
                e.Result.Read(byteImage, 0, byteImage.Length);
                isolatedStorageFileStream.Write(byteImage, 0, byteImage.Length);

                #endregion

                mediaFile.SetSource(isolatedStorageFileStream);
                mediaFile.Play();
                progressMedia.Visibility = Visibility.Collapsed;


            }
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
        }
    }

    private void mediaFile_MediaEnded(object sender, RoutedEventArgs e)
    {
        MessageBoxResult res = MessageBox.Show("Do you want to Replay the file", "Decide", MessageBoxButton.OKCancel);

        if (res == MessageBoxResult.OK)
        {
            mediaFile.Play();
        }
        else
        {
            isolatedStorageFileStream.Close();
            isolatedStorageFile.Dispose();
            mediaFile.ClearValue(MediaElement.SourceProperty);
        }
    }

异常详情:

System.OutOfMemoryException 未处理消息:System.Windows.ni.dll 中发生“System.OutOfMemoryException”类型的未处理异常

异常图像:

在此处输入图像描述

有解决方法吗?

4

1 回答 1

0

在完全加载响应时,它完全驻留在内存中。这会导致您的 OutOfMemoryException。解决方案是将响应直接“流式传输”到隔离存储中。

请注意,以下解决方案目前的缺点是您会丢失下载进度信息。

public async void btnDownload2_Click()
{
  try
  {
    var httpClient = new HttpClient();
    var response = await httpClient.GetAsync(new Uri("http://somelink/video/nameOfFile.mp4"), HttpCompletionOption.ResponseHeadersRead);

    response.EnsureSuccessStatusCode();

    using(var isolatedStorageFile = IsolatedStorageFile.GetUserStoreForApplication())
    {
      bool checkQuotaIncrease = IncreaseIsolatedStorageSpace(e.Result.Length);

      string VideoFile = "PlayFile.wmv";
      using(var isolatedStorageFileStream = new IsolatedStorageFileStream(VideoFile, FileMode.Create, isolatedStorageFile))
      {
        using(var stm = await response.Content.ReadAsStreamAsync())
        {
          stm.CopyTo(isolatedStorageFileStream);
        }
      }
    }
  }
  catch(Exception)
  {
    // TODO: add error handling
  }
}
于 2013-10-24T11:00:59.230 回答