void DownloadInternal(object obj)
{
if (this.Status != DownloadStatus.Waiting)
{
return;
}
try
{
this.EnsurePropertyValid();
// Set the status.
this.Status = DownloadStatus.Downloading;
if (!this.HasChecked)
{
string filename = null;
this.CheckUrlAndFile(out filename);
}
// If the file does not support "Accept-Ranges" header, then create one
// HttpDownloadClient to download the file in a single thread, else create
// multiple HttpDownloadClients to download the file.
if (!IsRangeSupported)
{
HttpDownloadClient client = new HttpDownloadClient(
this.Url.AbsoluteUri,
0,
long.MaxValue,
this.BufferSize,
this.BufferCountPerNotification * this.BufferSize,
this.BufferCountPerNotification);
// Set the HasChecked flag, so the client will not check the URL again.
client.TotalSize = this.TotalSize;
client.DownloadPath = this.DownloadPath;
client.HasChecked = true;
client.Credentials = this.Credentials;
client.Proxy = this.Proxy;
this.downloadClients.Add(client);
}
else
{
// Calculate the block size for each client to download.
int maxSizePerThread =
(int)Math.Ceiling((double)this.TotalSize / this.MaxThreadCount);
if (maxSizePerThread < this.MaxCacheSize)
{
maxSizePerThread = this.MaxCacheSize;
}
long leftSizeToDownload = this.TotalSize;
// The real threads count number is the min value of MaxThreadCount and
// TotalSize / MaxCacheSize.
int threadsCount =
(int)Math.Ceiling((double)this.TotalSize / maxSizePerThread);
for (int i = 0; i < threadsCount; i++)
{
long endPoint = maxSizePerThread * (i + 1) - 1;
long sizeToDownload = maxSizePerThread;
if (endPoint > this.TotalSize)
{
endPoint = this.TotalSize - 1;
sizeToDownload = endPoint - maxSizePerThread * i;
}
// Download a block of the whole file.
HttpDownloadClient client = new HttpDownloadClient(
this.Url.AbsoluteUri,
maxSizePerThread * i,
endPoint);
// Set the HasChecked flag, so the client will not check the URL again.
client.DownloadPath = this.DownloadPath;
client.HasChecked = true;
client.TotalSize = sizeToDownload;
client.Credentials = this.Credentials;
client.Proxy = this.Proxy;
this.downloadClients.Add(client);
}
}
// Set the lastStartTime to calculate the used time.
lastStartTime = DateTime.Now;
// Start all HttpDownloadClients.
foreach (var client in this.downloadClients)
{
if (this.Proxy != null)
{
client.Proxy = this.Proxy;
}
// Register the events of HttpDownloadClients.
client.DownloadProgressChanged += client_DownloadProgressChanged;
client.StatusChanged += client_StatusChanged;
client.DownloadCompleted += client_DownloadCompleted;
client.BeginDownload();
}
}
catch (Exception ex)
{
this.Cancel();
this.OnDownloadCompleted(new DownloadCompletedEventArgs(
null,
this.DownloadedSize,
this.TotalSize,
this.TotalUsedTime,
ex));
}
}