我有以下多線程代碼摘錄,我一直在努力比較壓縮副本和解壓縮後的文件。 應用程序正在壓縮包含可變數量的各種大小文件的文件夾,將文件複製到服務器並解壓縮它們。然後比較這些文件,並將此比較結果輸出到ThreadPool
。使用CountdownEvent和ManualResetEvent控制ThreadPool中的線程
這裏是目前全法:
public void FolderMoverLogic(string folderPathToZip, string unzipOutputDir)
{
string folderRootDir = Path.GetDirectoryName(folderPathToZip);
string folderNameToZip = Path.GetFileName(folderPathToZip);
try
{
//Zips files in <folderPathToZip> into folder <zippedLocal>
TransferMethods.CreateZipExternal(folderPathToZip, zippedlocal);
//Copies zipped folder to server location
File.Copy(zippedlocal + "\\" + folderNameToZip + ".zip", zippedserver + "\\" + folderNameToZip + ".zip");
//Unzips files to final server directory
TransferMethods.UnZip(zippedserver + "\\" + folderNameToZip + ".zip", unzipOutputDir + "\\" + folderNameToZip, sizeof(Int32));
TransferMethods m = new TransferMethods();
//Enumerate Files for MD5 Hash Comparison
var files = from file in Directory.EnumerateFiles(folderPathToZip, "*", SearchOption.AllDirectories)
select new
{
File = file,
};
int fileCount = 0;
CountdownEvent countdown = new CountdownEvent(10000);
using (ManualResetEvent resetEvent = new ManualResetEvent(false))
{
foreach (var f in files)
{
Interlocked.Increment(ref fileCount);
countdown.Reset(fileCount);
try
{
ThreadPool.QueueUserWorkItem(
new WaitCallback(c =>
{
//Check if any of the hashes have been different and stop all threads for a reattempt
if (m.isFolderDifferent)
{
resetEvent.Set();
CancellationTokenSource cts = new CancellationTokenSource();
cts.Cancel(); // cancels the CancellationTokenSource
try
{
countdown.Wait(cts.Token);
}
catch (OperationCanceledException)
{
Console.WriteLine("cde.Wait(preCanceledToken) threw OCE, as expected");
}
return;
}
else
{
//Sets m.isFolderDifferent to true if any files fail MD5 comparison
m.CompareFiles(f.File, folderRootDir, unzipOutputDir);
}
if (Interlocked.Decrement(ref fileCount) == 0)
{
resetEvent.Set();
}
countdown.Signal();
}));
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
countdown.Wait();
resetEvent.WaitOne();
resetEvent.Close();
}
}
catch (Exception Ex)
{
Console.WriteLine(Ex.Message);
}
}
有用的資源看着迄今:
Is it safe to signal and immediately close a ManualResetEvent?
Stopping all thread in .NET ThreadPool?
個線程池的邏輯要求:
- 對比所有枚舉文件在本地和服務器上的所有線程
- 返回如果散列不匹配
以前線程池代碼:
using (ManualResetEvent resetEvent = new ManualResetEvent(false))
{
foreach (var f in files)
{
testCount++;
try
{
//Thread t = new Thread(() => m.CompareFiles(f.File, unzipped, orglsource));
//t.Start();
//localThreads.Add(t);
ThreadPool.QueueUserWorkItem(
new WaitCallback(c =>
{
if (resetEvent.WaitOne(0)) //Here is the `ObjectDisposedException`
{
return;
}
if (!m.Folderdifferent)
{
m.CompareFiles(f.File, folderRootDir, unzipOutput);
}
else
{
resetEvent.Set();
}
if (Interlocked.Decrement(ref fileCountZipped) == 0)
{
resetEvent.Set();
}
}));
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
resetEvent.WaitOne();
}
我得到ObjectDisposedExceptions
定期與pre顯示的vious代碼。
我的問題是這樣:
- 是當前方法的線程安全的嗎?
- 是邏輯聲音?
- 性能或線程安全的任何改進意見
- 是否當前的方法我在上面解決了前面的代碼例外
我一直在測試這個代碼,它一直沒有例外,但我看一些更有經驗的反饋。
你在問錯誤的問題。當你使用線程時,你還沒有檢查你的代碼實際上是否更快。不是這樣。因此,嘗試使這個危險和麻煩的代碼工作是沒有意義的。 – 2013-03-17 00:16:43
@HansPassant如果我正在使用的文件大小大於1 GB,那麼它們可以提供幫助? – jordanhill123 2013-03-17 00:19:10
你不應該問我。你應該*測量*。和不。 – 2013-03-17 00:20:49