【发布时间】:2020-11-01 06:06:47
【问题描述】:
我有一组嵌套方法可以有效地复制文件以进行备份,然后使用“RecordConsolidator”类对该文件进行更改。在事件链中,我得到文件正在使用的随机异常,这对我来说没有意义,除非 Parallel.For 调用中的每一行代码都是异步执行的。这是我当前问题的一个示例(在注释行中):
// this is from a method called CompactFormIDs
try
{
// will this ever be executed twice on the same object? Will it be
// released before the next line of code after the catch statement?
File.Copy(dest, source);
}
catch (Exception e)
{
weirdExceptions.Add(source); // I keep getting a message that the file already exists
// even though there is only one copy statement which copies the file above.
}
// creates an undo step in a batch file
Globals.AddCommit(CommitType.RestoreBackup | CommitType.UndoDeleteBackup | CommitType.CommitDeleteBackup, source, dest);
HashSet<FormID> npcList = new HashSet<FormID>();
uint mask = (uint)masters.Count << 24;
report.BeginAppendProcess();
// the method below also causes an exception.
// It acts as though the file copied is still in use. No other process accesses the file other than the
// copy process before this statement. When not doing Parallel.For this works just fine.
using (RecordConsolidator consolidator = new RecordConsolidator(source, dest, mask, npcList))
{...
}
最终目标是:
-
制作将要修改的文件的副本,以便在新版本的文件不能正常工作时恢复它。
-
将原始文件的恢复添加到批处理脚本中
-
对文件进行更改。
如何使用 Parallel.For 方法在并行进程中执行此操作,而不会遇到所有这些“文件正在使用/存在”问题。这里甚至存在问题的事实是没有意义的,因为单个 Copy 语句会导致多个不应发生的问题,除非在执行其余代码之前副本未完成或以某种方式执行 Parallel.For 两次每个项目。
更新 1:这是包含 Parallel.For 循环的方法:
private void OnFormShown(object sender, EventArgs e)
{
Mod mod;
RichTextboxBuilder builder;
List<Mod> batch = task as List<Mod>;
Refresh();
if (batch != null)
{
RichTextboxBuilder.BeginConcurrentAppendProcess(this, batch.Count);
ReportCaption = "Conversion Progress";
progressBar.Visible = true;
progressBar.Maximum = batch.Count;
Parallel.For(0, batch.Count, i =>
{
mod = batch[i];
builder = RichTextboxBuilder.BeginConcurrentAppend(i);
//builder.TextUpdated += Builder_TextUpdated;
taskTarget.ConvertToESL(mod, builder, false);
RichTextboxBuilder.EndConcurrentAppend(i);
});
Finalize(false);
}
else
{
mod = task as Mod;
ReportTextBuilder = new RichTextboxBuilder(this);
Finalize(taskTarget.ConvertToESL(mod, ReportTextBuilder));
}
}
【问题讨论】:
-
问:这会在同一个对象上执行两次吗?答:我们不知道。那是你来决定的。根据您未显示的代码(分配“dest”和“source”的代码)- 会吗?你告诉我们!
-
我使用了一个哈希集,如果 Add 方法有效则允许处理,然后在处理时从 hasset 中删除。
-
没有。只有一个 Parallel.For 调用。我会将它添加到我的代码中。
-
我刚刚意识到一些事情(从我发布的代码中可以看出)。有时消息循环会收到双重消息。由于 parallel.for 在消息处理程序中执行,也许这就是它发生的原因?
-
什么是
taskTarget它不是函数本地的
标签: c# system.io.file parallel.for