我正在开发一个创建数十万个硬链接的应用程序(这是应用程序的核心功能)。
我使用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的一部分,因此在UNMANAGED代码中运行。我对并行ctp的了解是并行任务必须在托管代码中运行。 createhardlink是否有托管替代方案?有谁知道如何在托管代码中创建硬链接,是否有人对并行编程和使用非托管代码有任何想法?
答案 0 :(得分:1)
尝试以并行方式创建硬链接毫无意义。这不是CPU绑定操作,而是I / O绑定。与天真的连续方法相比,我不希望这种方法带来任何性能上的好处。
关于与硬链接创建相关的托管代码和非托管代码的问题很有意思。您必须记住,托管代码的任何I / O访问都会在某些时候调用非托管代码。操作系统不受管理,创建硬链接的唯一方法是通过操作系统。我认为您需要更准确地了解CTP对托管代码的这种限制究竟意味着什么。
答案 1 :(得分:0)
如果您希望能够取消硬链接创建,但又不想进行多线程处理,我要做的是实现生产者/消费者队列 - 一个或多个线程添加“在此路径创建硬链接”工作项队列,一个线程从队列中抓取工作项并为它们创建硬链接。
这为您提供了一些取消的灵活性 - 如果您想要停止所有硬链接创建,您可以中止工作线程,或者如果您只想取消一个项目,您可以在队列中找到它并将其删除。
查看您发布的代码的旁注 - 调用Application.DoEvents()是纯粹的,毫不畏惧的邪恶。每当你打电话给它时,一个小海豹就会自杀身亡。一个更好的方法是在你的用户界面上queue a work item在线程池上,然后使用Dispatcher.Invoke(假设这是WPF - 如果它是Winforms我知道有一个等价但我不知道是什么它是异步更新UI。
答案 2 :(得分:0)
并行使用非托管OS调用不再是从托管代码执行操作的问题。就那么简单。 :)
托管代码只是意味着它在托管上下文中运行(因此CLR可以跟踪事物)。执行方面,无论是托管还是非托管都无关紧要。
如果我没记错,任何kernel32调用都是原子的,这意味着它是线程安全的。