2013-12-20 33 views
1

我正在做一个小小的下载管理器与C#WPF在C中使用多线程的正确方法

在我的逻辑中有一个主线程(用于UI),用于管理连接的线程和每个下载的线程,直到我用信号量定义的最大下载数量。

每当用户想要下载某个东西时,它会在共享队列中添加一个自定义对象DownloadDetails,连接线程会将其解除锁定并使另一个线程执行实际下载。

对于单个文件,它工作正常,但对于多个文件看起来像更多的线程尝试下载相同的文件,试图写入本地驱动器上的相同文件,并在写入流时崩溃。

这里我实现的一些片段

主要形式:

private Thread connectionManager; 

时clickin下载我添加新的下载(他们是正确的,我检查),并启动连接线只有当它尚未启动:

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); 
    }); 

    ... 
} 

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类建立一个下载管理器。

+0

你确定吗?调试它我总是有一个不同的值,因为“TryDequeue”实际上是从队列中删除值...并且此循环由单个线程完成,因此无法在同一时刻多次完成 – HypeZ

+0

尝试使用localCopy固定。它适合_looks像更多的线程尝试下载相同的file_症状。 –

+0

尝试..和..工作!谢谢:)但我仍然不明白它为什么会起作用,这怎么会发生呢? – HypeZ