产生了很多线程。系统似乎排队线程

时间:2015-11-23 06:56:44

标签: c# multithreading

我对线程很新,所以我的实现无疑是非常简陋的。

我正在尝试使用FTPWebRequest生成每个下载文件的8个或更多线程,以便并行运行。

所有线程似乎都在产生并完成他们的工作,但只有两个线程在任何时候都可以工作。他们似乎排队了。

任何人都可以建议我可能做错了什么以及如何解决这个问题?

private void btnDownload_Click(object sender, EventArgs e)
    {
        int itemCount = lBoxList.Items.Count;
        string[] listOfFilesToDownload = new string[itemCount];

        for (int i = 0; i < itemCount; i++)
        {
            listOfFilesToDownload[i] = (string)lBoxList.Items[i];
        }

        FtpParallelDownload("ftp://ftp.somedomain.com/sub/sub2/sub3/", (int)this.nudNumberOfThreads.Value, listOfFilesToDownload, tBoxDownloadPath.Text);

    }

public static void FtpParallelDownload(string serverUri, int maxNumberOfThreads, string[] listOfFilesToDownload, string downloadPath)
    {
        int progressPercent = 0;

        // Validate number of threads requested
        if (!(maxNumberOfThreads >= 1))
        {
            ArgumentException e = new ArgumentException();
            throw e;
        }

        // Calc number of files based on array length
        int numberOfFiles = listOfFilesToDownload.Length;

        // Don't spawn more threads than files
        if (maxNumberOfThreads > numberOfFiles)
        {
            maxNumberOfThreads = numberOfFiles;
        }            

        // Thread spawning

        List<Thread> threadPool = new List<Thread>();

        int runningThreadCount = 0;



        for (int i = 0; i < numberOfFiles; i++)
        {
            if (runningThreadCount < maxNumberOfThreads)
            {
                Thread workerThread = new Thread(() => FtpDownloadFile(serverUri, listOfFilesToDownload[i], downloadPath));
                threadPool.Add(workerThread);
                workerThread.Start();
                runningThreadCount++;                   
            }
            else
            {
                i--;
            }

            List<Thread> removeThreadList = new List<Thread>();
            foreach (Thread t in threadPool)
            {
                if (!t.IsAlive)
                {
                    removeThreadList.Add(t);
                }
            }

            foreach (Thread t in removeThreadList)
            {
                threadPool.Remove(t);
                runningThreadCount--;
            }
            removeThreadList.Clear();
        }

        MessageBox.Show("DOWNLOADS COMPLETE!");
    }

    private static void FtpDownloadFile(string serverUri, string fileName, string downloadPath)
    {
        try
        {
            FtpWebRequest request = (FtpWebRequest)FtpWebRequest.Create(new Uri(serverUri + fileName));
            request.Method = WebRequestMethods.Ftp.DownloadFile;
            request.Credentials = new NetworkCredential("anonymous", "noreply@mydomain.com");
            FtpWebResponse response = (FtpWebResponse)request.GetResponse();
            Stream responseStream = response.GetResponseStream();
            FileStream writeStream = new FileStream(downloadPath + "/" + fileName, FileMode.Create);

            int Length = 4096;
            Byte[] buffer = new Byte[Length];
            int bytesRead = responseStream.Read(buffer, 0, Length);
            while (bytesRead > 0)
            {
                writeStream.Write(buffer, 0, bytesRead);
                bytesRead = responseStream.Read(buffer, 0, Length);
                Thread.Sleep(10);

            }
            writeStream.Close();
            response.Close();
            responseStream.Close();
        }

        catch (WebException wEx)
        {
            MessageBox.Show(wEx.Message, "Download Error");
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message, "Download Error");
        }
    }

threadPoolThread<List>,用于监控活动的线程数,以便在完成工作后产生更多线程。

1 个答案:

答案 0 :(得分:1)

你真的应该使用现有的库,而不是自己编辑。

以下是使用Microsoft的Reactive Framework(NuGet“Rx-WinForms”)编写代码的方法。

public static void FtpParallelDownload(
    string serverUri, int maxNumberOfThreads,
    string[] listOfFilesToDownload, string downloadPath)
{
    listOfFilesToDownload
        .ToObservable()
        .Select(x => Observable.Start(() => FtpDownloadFile(serverUri, x, downloadPath)))
        .Merge(maxNumberOfThreads)
        .ObserveOn(this)
        .ToArray()
        .Subscribe(xs => { }, () => { MessageBox.Show("DOWNLOADS COMPLETE!"); });
}

完成。