-2

I have a project to download using multithread over Http. It downloads the content partially.

For some URLs and low download speed, some of the partial download threads waits too much on while loops' without getting data and after a few times the thread directly exits without executing the code after the while loop. I don't understand how can it be.

My code:

    void DownloadProcedure()
    {
        file = new FileStream(this.FullPath,
                                FileMode.Create, FileAccess.ReadWrite);
        #region Request-Response
        ServicePointManager.Expect100Continue = true;
        ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls
            | SecurityProtocolType.Tls11
            | SecurityProtocolType.Tls12
            | SecurityProtocolType.Ssl3;

        HttpWebRequest req = WebRequest.Create(url) as HttpWebRequest;
        req.Accept = "*/*";
        req.Timeout = 3000;
        req.UserAgent = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; .NET CLR 1.0.3705;)";
        req.AllowAutoRedirect = true;
        req.MaximumAutomaticRedirections = 5;
        req.ServicePoint.ConnectionLimit += 2;
        req.ServicePoint.Expect100Continue = true;
        req.ProtocolVersion = HttpVersion.Version10;
        if (rangeAllowed)
            req.AddRange(from, to);
        resp = req.GetResponse() as HttpWebResponse;

        #endregion

        #region Some Stuff
        contentLength = resp.ContentLength;
        if (rangeAllowed && contentLength != to - from + 1)
            throw new Exception("Incorrect response content");

        tempStream = resp.GetResponseStream();
        int bytesRead = 0;
        byte[] buffer = new byte[4096];
        stp.Start(); 
        #endregion

        #region Procedure Loop
        while ((bytesRead = tempStream.Read(buffer, 0, buffer.Length)) > 0)
        {
            while (wait) ;

            if (totalBytesRead + bytesRead > contentLength)
                bytesRead = (int)(contentLength - totalBytesRead);
            file.Write(buffer, 0, bytesRead);
            totalBytesRead += bytesRead;
            last40Speed[counter] = (int)(totalBytesRead / Math.Ceiling(stp.Elapsed.TotalSeconds));
            counter = (counter >= 39) ? 0 : counter + 1;
            double tempProgress = Helper.GetTwoDigits(totalBytesRead * 1d / contentLength * 100);
            if (progress != tempProgress)
            {
                progress = tempProgress;
                aop.Post(new SendOrPostCallback(delegate
                {
                    if (DownloadPartProgressChanged != null)
                        DownloadPartProgressChanged(this, EventArgs.Empty);
                }), null);
            }
            if (stop || (rangeAllowed && totalBytesRead == to - from + 1))
            {
                break;
            }
        }
        #endregion

        #region Close Resources
        file.Close();
        resp.Close();
        tempStream.Close();
        req.Abort();
        resp.Dispose();
        stp.Stop();
        #endregion

        Debug.WriteLine("Threads' exit");
}

In this code every download threads have to execute the Debug.WriteLine code at the last line, but some of them doesn't execute it. The output says The thread 0x... has exited with code 259 (0x103). for each thread, but doesn't write Threads' exit for each.

The output:

enter image description here

Download status

enter image description here

As you see, some of the download threads stops and exits directly. What is the reason of this problem?

UPDATE:

Thread creation:

    public void Start()
    {
        Task th = new Task(() =>
        {
            createFirstPartitions();
        });
        th.Start();
    }
    void createFirstPartitions()
    {
        size = Helper.GetContentLength(url, ref rangeAllowed, ref url);

        for (int i = 0; i < numberOfParts; i++)
        {
            PartialDownloader temp = createNewPD(i, numberOfParts, size);
            temp.DownloadPartProgressChanged += temp_DownloadPartProgressChanged;
            temp.DownloadPartCompleted += temp_DownloadPartCompleted;
            pdlist.Add(temp);
            temp.Start();
            totalPartition++;
        }
    }

    PartialDownloader createNewPD(int order, int parts, long contentLength)
    {
        long division = contentLength / parts;
        long remaining = contentLength % parts;
        long start = division * order;
        long end = start + division - 1;
        end += (order == parts - 1) ? remaining : 0;
        return new PartialDownloader(url, tempDirectory,
                                        Guid.NewGuid().ToString(), start, end, true);
    }
Ali Tor
  • 2,772
  • 2
  • 27
  • 58
  • Your threads are exiting with a non-zero exit code (i.e. there's an error, probably due to an exception). What does the Output window tell you? – Cameron Nov 21 '16 at 19:41
  • These are the download threads created in code. The first seven threads are successfull and the others are not. Output also says `The program '[3988] MultiThreadingDownloder.vshost.exe: Program Trace' has exited with code 0 (0x0).` `The program '[3988] MultiThreadingDownloder.vshost.exe' has exited with code 0 (0x0).` – Ali Tor Nov 21 '16 at 19:44
  • Also, you haven't shown us the threading part... where do `from` and `to` come from? And `wait`? – Cameron Nov 21 '16 at 19:46
  • I have updated my question. `wait` is a simple variable that helps me to wait the thread for a few milliseconds to keep its variables the same until some operations are done. `from` and `to` are the range variables calculated to create partial content. – Ali Tor Nov 21 '16 at 19:53

1 Answers1

0

I have found a simple answer for my question. The solution is using HttpWebRequest.ReadWriteTimeout. By default its value is 5 minutes. Setting it to an acceptable time is a good solution.

Add req.ReadWriteTimeout = 5000 while sending the request.

Then change the code part to this:

        try
        {
            while ((bytesRead = tempStream.Read(buffer, 0, buffer.Length)) > 0)
            {
                //....
                file.Write(buffer, 0, bytesRead);
                totalBytesRead += bytesRead;
            }
        }
        catch
        {
            //Refresh the connection
        }
Ali Tor
  • 2,772
  • 2
  • 27
  • 58