2013-12-20 34 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