2011-04-29 52 views
1

我正在開發一個創建數十萬個硬鏈接(這是應用程序的核心功能)的應用程序。在託管代碼中創建硬鏈接

我使用了dotNET 4.0現在提供的並行編程功能。這工作得很好。請參閱下面的示例snippits。

或者:

Parallel.For(from, until, delegate(int i) 
{ 
    j += 1; 
    fileIndex = Convert.ToInt32(Math.Round(j * 0.001) + 1); 

    //determine the hardlink files; we have to have an unique name for the hardlink for each individual hardlink 
    fileName = fiArray[fileIndex].Name; //Path.GetFileNameWithoutExtension(textBoxFile.Text); 
    destinationFileName = Path.Combine(textBoxDestination.Text, string.Concat(fileName, "_", i.ToString(), ".txt")); 

    fr.CreateHardLink(destinationFileName, fiArray[fileIndex].FullName); 
}); 

或者:

//loop that does the actual work 
for (int i = 0; i < nudThreads.Value; i++) 
{ 
    //determine the work package per task 
    from = 0 + until + 1; 
    until = (i * (Convert.ToInt32(HardLinks/ThreadNo))) + 1; 
    var compute = Task.Factory.StartNew(() => 
    { 
     token.ThrowIfCancellationRequested(); //uit boek 
     return Work(from, until, false);//todo: counter moet nog worden meegenomen 
    }, tokenSource.Token); 

    tasks.Add(compute); 

    var displayResults = compute.ContinueWith(resultTask => UpdateControls(), 
          CancellationToken.None, 
          TaskContinuationOptions.OnlyOnRanToCompletion, 
          ui); 
    CheckedListBoxFiles.Items.Add(DateTime.Now.ToString() + " : Created the hardlinks for: " + displayResults + " files."); 
    Application.DoEvents(); 

    var displayCancelledTasks = compute.ContinueWith(resultTask => UpdateControls(), 
           CancellationToken.None, 
            TaskContinuationOptions.OnlyOnCanceled, ui); 
    CheckedListBoxFiles.Items.Add(DateTime.Now.ToString() + " : Cancelled a task at: " + displayCancelledTasks + " files."); 
    Application.DoEvents(); 
} 

的問題我已經是這樣的:CreateHardlink是Kernel32.dll中的一部分,因此運行在非託管代碼。我所知道的並行ctp是並行任務必須以託管代碼運行。 是否有可用於createhardlink的託管替代方案?有誰知道如何在託管代碼中創建硬鏈接,並且沒有人有關於並行編程和使用非託管代碼的任何提示嗎?

+0

只是一個小紙條...我意識到這可能不是你所有的代碼,但以防萬一:你在並行上下文中設置fileIndex,fileName和destinationFileName,但它似乎是在上下文之外定義的。這會導致難以檢測到的競爭狀況 - 如果在kernel32調用之後沒有檢查錯誤代碼,這幾乎是不可能的。 – 2011-04-29 19:02:15

回答

1

嘗試以並行方式創建硬鏈接沒有意義。這不是CPU綁定操作,而是I/O綁定。與天真的系列方法相比,我不希望這種方法可以帶來任何性能方面的好處。

有關與硬鏈接創建有關的託管代碼和非託管代碼的問題很有趣。您必須記住,託管代碼的任何I/O訪問都會在某些時候調用非託管代碼。操作系統不受管理,創建硬鏈接的唯一方法是通過操作系統。我認爲您需要更精確地確定CTP對託管代碼的這種限制的真正含義。

+0

我使用並行編程的原因是應用程序還需要跟蹤一些soap調用,並且我們希望能夠在某些時候鎖定hardlink創建。使用並行任務,可以捕獲任何異常並對其執行操作。 – essaver 2011-04-29 10:52:59

+0

好吧,我假設你試圖在多核機器上獲得性能優勢。 – 2011-04-29 10:54:03

+0

創建硬鏈接時遇到的問題是,當您創建多個threaded時出現某種原因時會出現停頓。這可能是由於處理速度快於磁盤IO的速度。因此,在這種情況下,處理並行任務和取消令牌功能的處理非常方便。 – essaver 2011-04-29 11:46:08

0

如果你想取消硬鏈接的創建,但不想多線程,我會做的是實現一個生產者/消費者隊列 - 一個或多個線程添加「在此路徑上創建硬鏈接」工作項目到隊列,並且一個線程從隊列中抓取工作項併爲它們創建硬鏈接。

這給你一些取消的靈活性 - 如果你想停止所有的硬鏈接創建,或者如果你想只取消一個項目,你可以在隊列中找到並刪除它,你可以中止工作線程。

查看您發佈的代碼的旁註 - 調用Application.DoEvents()是純粹的,毫不容錯的邪惡。每當你打電話給它,一個小海豹會自己死亡。一個更好的方法是將線程池上的UI設置爲queue a work item,然後使用Dispatcher.Invoke(假設這是WPF - 如果它是Winforms,我知道有一個等價物,但我不知道它是什麼)異步更新UI 。

0

並行使用非託管OS調用不是一個比從託管代碼執行更麻煩的問題。就那麼簡單。 :)

託管代碼只是表示它在託管上下文中運行(因此CLR可以跟蹤事物)。明智的執行方式不管它是託管還是非託管。

如果我不記得它錯了,任何kernel32-call都是原子的,這意味着它是線程安全的。