我正在用 做一个小下载管理器C# 和 WPF .
在我的逻辑中,有一个主线程(用于 UI)、一个用于管理连接的线程和一个用于每次下载的线程,直到我使用 定义的最大下载数。信号量 .
每次用户想要下载东西时,它都会添加一个自定义对象 DownloadDetails
在共享队列中,连接线程将其出列并让另一个线程进行实际下载。
对于单个文件,它工作正常,但对于多个文件,看起来更多线程尝试下载同一个文件,尝试在本地驱动器上写入同一个文件并在写入流时崩溃。
这是我实现的一些片段
在 主要 形式:
private Thread connectionManager;
当单击下载时,我添加了新的下载(它们都是正确的,我检查了它)并仅在连接线程尚未启动时才启动它:
downloadList.Enqueue(newDownload);
if (connectionManager == null || !connectionManager.IsAlive)
{
connectionManager = new Thread((ThreadStart)delegate
{
ManageDownload();
});
connectionManager.SetApartmentState(ApartmentState.STA);
connectionManager.IsBackground = true;
connectionManager.Start();
}
下载管理器线程这样做:
private void ThreadStartingPoint()
{
downloadDetails singleDownload = new downloadDetails();
while (downloadList.TryDequeue(out singleDownload))
{
downloadSemaphore.WaitOne();
Thread singleDownloadThread = new Thread((ThreadStart)delegate
{
myDownloadClass.Download(singleDownload);
});
singleDownloadThread.SetApartmentState(ApartmentState.STA);
singleDownloadThread.IsBackground = false;
singleDownloadThread.Start();
}
}
完成下载(或取消,或出错)后,单线程执行
downloadSemaphore.Release();
问题是 myDownloadClass.Download 快速开始 2 次或更多下载时看起来多次获得相同的参数
我必须使用委托(delegate),因为单个下载线程需要更新主线程上的 UI
我该如何解决这个问题?谢谢 :)
最佳答案
这个片段
while (downloadList.TryDequeue(out singleDownload))
{
downloadSemaphore.WaitOne();
Thread singleDownloadThread = new Thread((ThreadStart)delegate
{
myDownloadClass.Download(singleDownload);
});
...
}
是 capturing the loop-variable .
修复:
while (downloadList.TryDequeue(out singleDownload))
{
string localCopy = singleDownload;
downloadSemaphore.WaitOne();
Thread singleDownloadThread = new Thread((ThreadStart)delegate
{
myDownloadClass.Download(localCopy);
});
...
}
作为更一般的建议,我会使用
Task
s,也许是 Parallel
类来构建一个下载管理器。
关于c# - 在 C# 中使用多线程的正确方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20703100/