文档文件无法正确保存
我有一个在多个线程上创建文件的脚本。有时,我会在 document.SaveAs() 调用中收到以下错误:
{"Word 无法保存或创建此文件。请确保您的磁盘 要保存的文件未满、写保护或已损坏。\r (C:\...\文件名.docx)"}
这很令人抓狂,因为它似乎有时会发生,而其他时候则不会。我花了最后一天的时间试图弄清楚它,但进展甚微。有一件事我已经排除了多个线程尝试创建同一文件的可能性,我确定这不会发生,我的代码中是否缺少任何内容,或者这只是一个事实。使用 com 对象时我到底在做什么?代码教程说,也许我应该放弃使用多线程?
BuildDocumentsThread(){
var word = new Microsoft.Office.Interop.Word.Application();
word.Options.CreateBackup = false;
var wordQuit = (Microsoft.Office.Interop.Word._Application)word;
foreach(var value in values){
FormBuilder.BuildSummaryForm(word, value);
}
wordQuit.Quit();
}
public static void BuildSummaryForm(Application word, string value) {
var summaryFormPath = Utilities.GetSummaryFilePath(value);
if (File.Exists(summaryFormPath))
File.Delete(summaryFormPath);
object path = summaryFormPath;
object readOnly = false;
object o = System.Reflection.Missing.Value;
var document = word.Documents.Add(ref o, ref o, ref o, ref o);
document.Activate();
Paragraph p1 = document.Content.Paragraphs.Add(ref o);
p1.Range.Font.Name = "Arial";
p1.Range.Font.Size = 10;
p1.Range.Text = value;
document.SaveAs(ref path, ref o, ref o, ref o, ref o, ref o, ref o, ref o, ref o, ref o, ref o, ref o, ref o, ref o, ref o, ref o);
document.Close();
}
I have a script that creates files on multiple threads. Occassionally, I will get the following error on the document.SaveAs() call:
{"Word cannot save or create this file. Make sure that the disk you
want to save the file on is not full, write-protected, or damaged.\r
(C:\...\fileName.docx)"}
This is maddening because it seems to happen sometimes and not others. I've been spending the last day trying to figure it out, and have made very little progress. One thing I have ruled out is the possibility of more than one thread trying to create the same file. I am certain this isn't happening. Is there anything I'm missing in my code that would be causing this, or is this just a fact of life when working with com objects? I'm doing exactly what code tutorials out there are saying, maybe I should abandon using multiple threads?
BuildDocumentsThread(){
var word = new Microsoft.Office.Interop.Word.Application();
word.Options.CreateBackup = false;
var wordQuit = (Microsoft.Office.Interop.Word._Application)word;
foreach(var value in values){
FormBuilder.BuildSummaryForm(word, value);
}
wordQuit.Quit();
}
public static void BuildSummaryForm(Application word, string value) {
var summaryFormPath = Utilities.GetSummaryFilePath(value);
if (File.Exists(summaryFormPath))
File.Delete(summaryFormPath);
object path = summaryFormPath;
object readOnly = false;
object o = System.Reflection.Missing.Value;
var document = word.Documents.Add(ref o, ref o, ref o, ref o);
document.Activate();
Paragraph p1 = document.Content.Paragraphs.Add(ref o);
p1.Range.Font.Name = "Arial";
p1.Range.Font.Size = 10;
p1.Range.Text = value;
document.SaveAs(ref path, ref o, ref o, ref o, ref o, ref o, ref o, ref o, ref o, ref o, ref o, ref o, ref o, ref o, ref o, ref o);
document.Close();
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
如果 SaveAs 不是线程安全的,如 John Koerner 在评论中所述,您可以尝试锁定 SaveAs 并关闭。
在这种情况下,我不确定多线程过程将不再有用,但这是最糟糕的尝试。至少您会知道错误是否来自 SaveAs 函数。
要在您的评论后添加一些信息:
添加一个类变量来创建锁
然后在您的工作人员中:
在这种情况下,不会同时执行任何保存操作。锁定关闭也可能是必要的
在这种情况下,您并不真正关心是否是否是同一个单词实例。在这两种情况下它都会起作用。
主要缺点是,如果保存操作占用了线程 95% 的时间,则多线程几乎毫无用处,因为通过锁定保存操作,只有 5% 的进程真正是多线程的。但是,如果“释放”用户界面并让用户在进程运行时继续工作是目标,那么这是一个可行的解决方案。
检查http://msdn.microsoft.com/en-us/library/c5kehkcz。 aspx 为锁定原理
If the SaveAs is not thread safe as describe by John Koerner in the comment, you could try to lock the SaveAs and Close.
In this case I'm mot sure the multithreading process will be usefull anymore, but it's worst a try. At least you will know if your error is coming from the SaveAs function.
To add some infromation following your comment:
add a class variable to create the lock
Then in you worker:
In this case, no save operation will be done at the same time. Locking the close as well may be necessary
In this case you don't really care if it's the same instance of word or not. in both case it will work.
The main drawback is that if the save operation take 95% of the time of the thread, multi threading become nearly useless because by locking the save operation, only 5% of the process is really multi threaded. However if "freeing" the ui and let the user continue working while the process is running is the aim, it's a viable solution.
Check http://msdn.microsoft.com/en-us/library/c5kehkcz.aspx for the lock pricinple