2017-03-22 32 views
4

我使用下面的程序來從一個目錄處理一組視頻:如何多線程我的代碼同時處理幾個文件,通過相同的功能?

AllVideos = new List<MyVideo>(); 

for (int i = 0; i < AllVideosFileNames.Length; i++) 
{ 
    MyVideo CurrentVid = new MyVideo(AllVideosFileNames[i], false); // constructor (loads the video to the system) 
    CurrentVid.PopulateAllFrames(); // Method that takes forever 
    CurrentVid.PopluateTestFrames(); // Method that takes less than forever 
    CurrentVid.NormalizeTestFrames(); // Method that takes some time 
    AllVideos.Add(CurrentVid); // Add finished object to my results container 
} 

我想在同一時間處理的幾部影片,在並行,並節省時間。我試圖這樣做:

for (int i = 0; i < AllVideosFileNames.Length; i++) 
{ 
    Thread TempThread = new Thread(() => 
    { 
     MyVideo CurrentVid = new MyVideo(AllVideosFileNames[i], false); 
     CurrentVid.PopulateAllFrames(); 
     CurrentVid.PopluateTestFrames(); 
     CurrentVid.NormalizeTestFrames(); 
     AllVideos.Add(CurrentVid); 
    }); 
    TempThread.Start(); 
} 

但是,這執行得如此之快,沒有字面意思。無意義的意思是,當我遍歷代碼時,當循環結束執行時,AllVideos爲空。

更好的設計的任何想法?或修復?請和謝謝。

+2

嘗試使用/學習TPL哪個更更好,你控制研究已經在你的任務。[參見本(https://msdn.microsoft.com/en-us/library/dd460717(V = vs.110) .aspx) –

+0

如果您只是爲每件作品啓動一個線程,則父線程將繼續。你必須等待他們完成。我寧願爲每個創建一個任務(使用'Task.Run'),然後在創建的任務創建後對其執行「Task.Wait」。然後它們將平行運行完成 – Baldrick

+0

它在正常循環中持續一次迭代多長時間?看起來你的線程在循環結束時運行。 「AllVideos」呢?它從何而來?如果它不是局部變量,則可能有競態條件問題。考慮鎖定 –

回答

3

也許看看TPL和/或PLINQ。你知道嗎.AsParallel()

如何:

AllVideos = AllVideosFileNames 
    .AsParallel() 
    .Select(fileName => GetVideo(filename)) 
    .ToList(); 

GetVideo(filename)作爲遵循定義:

private MyVideo GetVideo(string filename) 
{ 
    MyVideo currentVid = new MyVideo(filename, false); 
    currentVid.PopulateAllFrames(); 
    currentVid.PopluateTestFrames(); 
    currentVid.NormalizeTestFrames(); 
    return currentVid; 
} 

更多信息請參見Introduction to PLINQ

+2

'AllVideosFileNames [i]'應該是'文件名' –

+2

@MatiasCicero謝謝你的支持!它現在已經修復。 – PJvG

+0

嗨,謝謝。有沒有辦法知道何時處理完所有文件? (不,我不知道'AsParallel',但它看起來很棒) –

3

你可以嘗試使用Parallel.ForEach。它會等到最後一個線程繼續之前完成其執行:

Parallel.ForEach(AllVideosFileNames, item => 
{ 
    MyVideo CurrentVid = new MyVideo(item, false); 
    CurrentVid.PopulateAllFrames(); 
    CurrentVid.PopluateTestFrames(); 
    CurrentVid.NormalizeTestFrames(); 
    AllVideos.Add(CurrentVid); 

}); 

免責聲明:

如前所述,再次提請注意通過Dmitry BychenkoListAllVideos不是線程保存。你可能想考慮鎖定:

Parallel.ForEach(AllVideosFileNames, item => 
{ 
    MyVideo CurrentVid = new MyVideo(item, false); 
    CurrentVid.PopulateAllFrames(); 
    CurrentVid.PopluateTestFrames(); 
    CurrentVid.NormalizeTestFrames(); 
    lock (AllVideos) 
    { 
     AllVideos.Add(CurrentVid); 
    }  
}); 
+0

我想我會在默認情況下等待最後一個線程完成。真棒修復謝謝Mong –

+0

不客氣。 –

+2

'AllVideos'成爲'List '是**不是線程安全的;這就是爲什麼你可以有'AllVideos.Add(CurrentVid);' –

相關問題