我正在使用 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次或更多下载时获得多次相同的参数
我必须使用委托,因为单个下载线程需要更新主线程上的UI
我该如何解决这个问题?谢谢:))
答案 0 :(得分:3)
这个片段
while (downloadList.TryDequeue(out singleDownload))
{
downloadSemaphore.WaitOne();
Thread singleDownloadThread = new Thread((ThreadStart)delegate
{
myDownloadClass.Download(singleDownload);
});
...
}
修复:
while (downloadList.TryDequeue(out singleDownload))
{
string localCopy = singleDownload;
downloadSemaphore.WaitOne();
Thread singleDownloadThread = new Thread((ThreadStart)delegate
{
myDownloadClass.Download(localCopy);
});
...
}
作为更一般的建议,我会使用Task
和Parallel
类来构建下载管理器。