我对线程很新,所以我的实现无疑是非常简陋的。
我正在尝试使用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");
}
}
threadPool
是Thread<List>
,用于监控活动的线程数,以便在完成工作后产生更多线程。
答案 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!"); });
}
完成。