Файл документа не будет сохранен должным образом - PullRequest
0 голосов
/ 22 февраля 2012

У меня есть скрипт, который создает файлы в нескольких потоках.Иногда я получаю следующую ошибку в документе. ВызовSaveAs ():

{"Word не может сохранить или создать этот файл. Убедитесь, что диск, на котором вы хотите сохранить файл, не являетсяполный, защищенный от записи или поврежденный. \ r (C: \ ... \ fileName.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();
}

1 Ответ

1 голос
/ 22 февраля 2012

Если SaveAs не является потокобезопасным, как описано Джоном Кернером в комментарии, вы можете попытаться заблокировать SaveAs и закрыть.

В этом случае я уверен, что многопоточный процесс больше не будет полезным, но это худшая попытка. По крайней мере, вы будете знать, если ваша ошибка исходит от функции SaveAs.


Чтобы добавить информацию после вашего комментария:

добавить переменную класса для создания блокировки

private static object _savelock = new object();

Тогда у вас рабочий:

lock(_savelock)
{
   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();

В этом случае операция сохранения не будет выполняться одновременно. Также может потребоваться блокировка закрытия

  • 1 поток взять замок и сохранить
  • Тем временем 2 потока попытайтесь сохранить, но подождите, пока предыдущий поток завершит сохранение и снимет блокировку

В этом случае вам все равно, является ли это тем же самым словом или нет. в обоих случаях это будет работать.

Основным недостатком является то, что если операция сохранения занимает 95% времени потока, многопоточность становится практически бесполезной, поскольку при блокировке операции сохранения только 5% процесса действительно многопоточны. Однако, если целью является «освобождение» пользовательского интерфейса и предоставление возможности пользователю продолжать работу во время работы процесса, это жизнеспособное решение.

Проверьте http://msdn.microsoft.com/en-us/library/c5kehkcz.aspx на стоимость замка в два раза

...