/// <summary>
        /// Starts the download task.
        /// </summary>
        public void StartDownload()
        {
            RemoteFileInfo remoteFileInfo = null;

            try
            {
                ChangeState(DownloadTaskState.Preparing);

                m_StartDate = DateTime.Now;

                INetworkProtocolProvider networkProtocolProvider = m_NetworkProtocolProviderFactory.CreateProvider(m_File.Uri);

                remoteFileInfo          = networkProtocolProvider.GetRemoteFileInfo(m_File);
                remoteFileInfo.FileName = m_File.FileName;

                m_FileSize    = remoteFileInfo.FileSize;
                m_IsResumable = remoteFileInfo.AcceptRanges;

                DownloadSegmentPositions[] segmentPositionInfos;

                if (remoteFileInfo.AcceptRanges)
                {
                    segmentPositionInfos = m_DownloadSegmentCalculator.Calculate(m_Settings.MinimumSegmentSize, m_Settings.MaximumSegmentCount, m_File.SegmentCount, remoteFileInfo.FileSize);
                }
                else
                {
                    segmentPositionInfos = new[] { new DownloadSegmentPositions(0, remoteFileInfo.FileSize - 1) };
                }

                using (Stream stream = m_DownloadStreamManager.CreateStream(remoteFileInfo))
                {
                    SegmentWriter segmentWriter = new SegmentWriter(stream);
                    SegmentDownloadTasks = new SegmentDownloadTaskCollection(segmentPositionInfos.Length);
                    for (int i = 0; i < segmentPositionInfos.Length; i++)
                    {
                        DownloadSegmentPositions segmentPosition = segmentPositionInfos[i];
                        SegmentDownloadTasks.Add(new DoubleBufferSegmentDownloadTask(m_Settings.DownloadBufferSize, new SegmentDownloader(m_File, networkProtocolProvider, segmentPosition, new SegmentDownloadRateCalculator(segmentPosition.StartPosition)), segmentWriter));
                    }

                    SegmentDownloadManager segmentDownloadManager = new SegmentDownloadManager(SegmentDownloadTasks);
                    segmentDownloadManager.Start();

                    ChangeState(DownloadTaskState.Working);

                    segmentDownloadManager.Finish(true);

                    ChangeState(DownloadTaskState.Ended);

                    m_EventManager.EventPublisher.Publish(new DownloadTaskFinishedEventMessage(this, stream, remoteFileInfo));
                }
            }
            catch (Exception ex)
            {
                if (m_RetryCount < m_Settings.MaximumRetries)
                {
                    m_RetryCount++;

                    StartDownload();
                }
                else
                {
                    m_LastException = ex;

                    ChangeState(DownloadTaskState.EndedWithError);

                    m_EventManager.EventPublisher.Publish(new DownloadTaskFinishedEventMessage(this, null, remoteFileInfo));
                }
            }
        }