2011-04-29 50 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都是原子的,这意味着它是线程安全的。