2012-02-22 12 views
0

複数のスレッドにファイルを作成するスクリプトがあります。 、ドキュメントファイルが正しく保存されない

{ "Wordがこのファイルを保存したり、作成することはできませんあなたが上にファイルを保存したい ディスクがいっぱいでないことを確認します。時折、私はdocument.SaveAs()の呼び出しに次のエラーを取得します書き込み保護、または破損\ 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(); 
} 
+0

SaveAsメソッドは、スレッドセーフではないため

チェックhttp://msdn.microsoft.com/en-us/library/c5kehkcz.aspx(http://msdn.microsoft.com/en-us/library/microsoft.office.interop.word.documentclass.saveas(v = office.11​​).aspx)。また、ファイルが別のプロセスによって保存または開かれている場合は、おそらくこのエラーが発生します。 –

+0

最初に私は質問する必要があります:あなたはこのアプリを実行している間に開いているMS Wordを持っていないのですか? – ardnew

+0

@JohnKoernerはスレッドセーフではないので、複数のスレッドで使用するべきではないということですか?私はページが何を意味するかを理解していません: "このタイプのpublic static(Visual BasicのShared)メンバはスレッドセーフです。"また、私は、一度に1つのスレッドだけが1つのファイルにアクセスしているという事実を知っています。 – sooprise

答えて

1

コメントにJohn Koernerが記述したようにSaveAsがスレッドセーフでない場合は、SaveAsとCloseをロックしようとする可能性があります。

この場合、私はマルチスレッドプロセスがもう役に立たないと確信していますが、最悪です。少なくとも、SaveAs関数からエラーが発生しているかどうかを知ることができます。


あなたのコメント以下のいくつかのinfromationを追加するには:

はあなたの労働者に続いてロック

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%だけが本当にマルチスレッドです。しかし、プロセスが実行されている間にUIを「フリー」にしてユーザーが作業を続けることが目的であれば、それは実行可能な解決策です。ロックpricinple

+0

これを理解するのを手伝ってもらえますか?たとえば、単語のインスタンスを1つだけ使用し、それを引数として各スレッドに送信するとします。もし私が任意のスレッドで単語をロックすると、その単語のインスタンスは他のすべてのスレッドでロックされますか、または各スレッドは一度起動するとwordのインスタンスのコピーを作成しますか? – sooprise

+0

これは非常に有用な投稿です。私は現在、それを保存しようとするスクリプトをテストしており、失敗した場合はオブジェクトをロックして保存を試みます。これが動作する限り、私はまだ複数のスレッドを使用するスピードの利点を得て、セーブが失敗したときのためのロックを持っています。 – sooprise

+0

Aww、うまくいかなかった:( – sooprise

関連する問題