I have an application where clients can download packages that are .zip files with average of 1GB.
When starting a download, a new thread is created that will make the request and via stream retrieves part of the bytes and writes to a file.
The problem is:
Start the first download and work correctly.
Start the second and also works correctly, the two downloads run simultaneously.
But when I start the third, the execution of the new thread is stopped waiting for the response in the command GetResponseAsync () (LINE 35), if I pause any of the previous downloads, yes, the code continues, probably because one of the WebResponse instances GetResponseAsync returned is closed.
I need to be able to download multiple packages at the same time.
The method responsible for downloading:
private async void DownloadPackage()
{
FileStream fileStream = null;
try
{
string appDataPath = GetAppDataPath();
int currentIndex = 0;
int bytesReceived = 0;
int currentRateBytes = 0;
long bytesSaved = 0;
HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create(new Uri(GetPackageUrl()));
if (File.Exists(appDataPath))
{
FileInfo fileInfo = new FileInfo(appDataPath);
fileStream = File.Open(appDataPath, FileMode.Append);
bytesSaved = fileInfo.Length;
req.AddRange(bytesSaved);
}
else if (File.Exists(GetZipPackagePath()))
{
if (Directory.Exists(appDataPath))
Directory.Delete(appDataPath, true);
File.Move(GetZipPackagePath(), appDataPath);
PreparePresentation();
DownloadCompleted();
return;
}
else
fileStream = File.Create(appDataPath);
using (WebResponse response = await req.GetResponseAsync().ConfigureAwait(false))
{
long contentLength = response.ContentLength;
using (Stream responseStream = response.GetResponseStream())
{
DateTime lastRateUpdate = DateTime.Now;
byte[] buffer = new byte[2560];
while (currentIndex < contentLength)
{
if (!continueDownload)
{
DownloadPaused();
break;
}
try
{
bytesReceived = responseStream.Read(buffer, 0, 2560);
currentRateBytes += bytesReceived;
fileStream.Write(buffer, 0, bytesReceived);
fileStream.Flush();
currentIndex += bytesReceived;
}
catch (Exception e)
{
if (tryCount == 5)
{
string msg = string.Format("Ocorreu um erro ao tentar fazer download do pacote, verifique sua conexão e tente novamente.\nErro: {0}", e.Message);
MessageBox.Show(msg);
tryCount = 0;
continueDownload = false;
this.Invoke((MethodInvoker)delegate
{
NeedDownload();
});
break;
}
else
{
tryCount++;
fileStream.Close();
response.Close();
DownloadPackage(new object(), new EventArgs());
return;
}
}
DateTime endTime = DateTime.Now;
if ((DateTime.Now - lastRateUpdate).TotalSeconds >= 2)
{
DownloadRate rate = CalculateRate(lastRateUpdate, endTime, currentIndex, contentLength, currentRateBytes);
double percentage = (double)(currentIndex + bytesSaved) / (contentLength + bytesSaved);
UpdateProgressBar((int)(percentage * 100), rate);
lastRateUpdate = DateTime.Now;
currentRateBytes = 0;
}
}
fileStream.Close();
}
response.Close();
if (continueDownload && PreparePresentation())
DownloadCompleted();
}
}
catch (Exception e)
{
string msg;
if(fileStream != null) fileStream.Close();
if (e is WebException && ((HttpWebResponse)((WebException)e).Response).StatusCode == HttpStatusCode.RequestedRangeNotSatisfiable)
{
try
{
if(PreparePresentation()) DownloadCompleted();
return;
}
catch (Exception ex)
{
msg = string.Format("Ocorreu um erro ao finalizar pacote.\nErro: {0}", e.StackTrace);
MessageBox.Show(msg, e.Message);
this.Invoke((MethodInvoker)delegate
{
NeedDownload();
});
return;
}
}
msg = string.Format("Ocorreu um erro ao tentar fazer download do pacote, verifique sua conexão e tente novamente.\nErro: {0}", e.Message);
MessageBox.Show(msg, "Erro");
this.Invoke((MethodInvoker)delegate
{
NeedDownload();
});
}
}
Method call:
private void DownloadPackage(object sender, EventArgs e)
{
//algumas verificações
ThreadStart ts = new ThreadStart(DownloadPackage);
new Thread(ts).Start();
}
Note: These methods are inside a UserControl for each available package. In that UserControl have buttons (to start and pause the download), progress bar, images, etc.