2015-07-06 15 views
6

Per riprodurre il problema, ho creato un progetto di console e al di sotto è il codice nel mio file Program.cs:ClosedXML .SaveAs (MemoryStream ms) non progredisce durante il salvataggio di un file xlsm due (ciascuno di circa 7MB) allo stesso tempo

using System; 
using System.IO; 
using System.Threading; 
using ClosedXML.Excel; 

namespace TestSavingTwoBigFiles 
{ 
    public class Program 
    { 
     private static string folderPath = @"C:\FOLDERPATH\"; 
     private static string fileName1 = folderPath + "FILENAME1.xlsm"; 
     private static string fileName2 = folderPath + "FILENAME2.xlsm"; 

     public static void StartThread(string ordinal, string fileName) 
     { 
      Console.WriteLine("Creating {0} file...", ordinal); 
      var wb = new XLWorkbook(fileName, XLEventTracking.Disabled); 
      try 
      { 
       using (wb) 
       { 
        using (var ms = new MemoryStream()) 
        { 
         Console.WriteLine("Saving {0} file...", ordinal); 
         wb.SaveAs(ms); 
        } 
       } 
       Console.WriteLine("{0} file saved successfully", ordinal); 
      } 
      catch (Exception ex) 
      { 
       Console.WriteLine(ex); 
       Console.ReadLine(); 
      } 
     } 

     public static void Main(string[] args) 
     { 
      var thread1 = new Thread(() => StartThread("first", fileName1)); 
      Console.WriteLine("Starting first thread"); 
      thread1.Start(); 

      var thread2 = new Thread(() => StartThread("second", fileName2)); 
      Console.WriteLine("Starting second thread"); 
      thread2.Start(); 
     } 
    } 
} 

[Grazie @EmilyLin per la versione pulita]

Quando eseguo il programma di cui sopra con due `file .xlsm uno è ~ 2 MB e l'altra è ~ 7MB, il programma viene completata correttamente. Tuttavia, quando lo eseguo con due file da ~ 7 MB, il programma verrà bloccato nelle istruzioni di salvataggio e non progredirà senza generare un'eccezione. La console rimarrà come l'immagine seguente mostra e non cambia.

Console Output

Una soluzione che abbiamo usato stava mettendo un blocco sul metodo di SaveAs. C'è un modo migliore?

Grazie!

+1

Questo suona come un problema con ClosedXML e vi consiglio di postare un problema su [progetto Codeplex degli sviluppatori] (https://closedxml.codeplex.com/workitem/list/base). –

+0

@TimRogers Grazie per la risposta! Ho pubblicato il problema nella pagina dei problemi del progetto CloseXML. [issue post] (https://closedxml.codeplex.com/workitem/9447) –

risposta

1

L'inserimento di un blocco sul metodo SaveAs è probabilmente il modo migliore. Nel codice sorgente per XLWorkbook.cs, entrambe le funzioni SaveAs utilizzano FileStream e/o MemoryStream. Nessuno dei due flussi è sicuro per i thread, quindi il codice potrebbe non funzionare se eseguito simultaneamente con più thread, quindi è necessario assicurarsi che solo un thread possa accedere allo MemoryStream allo stesso tempo.

Ecco un esempio:

using System; 
using System.IO; 
using System.Threading; 
using ClosedXML.Excel; 

namespace Whatever 
{ 
    class Class1 
    { 
     private static readonly object lockObject = new object(); 

     public static void StartThread(string ordinal, string fileName) 
     { 
      Console.WriteLine(string.Format("creating {0} file...", ordinal)); 
      var wb = new XLWorkbook(fileName, XLEventTracking.Disabled); 
      try 
      { 
       using (wb) 
       using (var ms = new MemoryStream()) 
       { 
        lock (lockObject) 
        { 
         Console.WriteLine(string.Format("saving {0} file...", ordinal)); 
         wb.SaveAs(ms); 
        } 
       } 
       Console.WriteLine(string.Format("{0} file saved successfully", ordinal)); 
      } 
      catch (Exception ex) 
      { 
       Console.WriteLine(ex); 
      } 
     } 

     public static void Main(string[] args) 
     { 
      var thread1 = new Thread(() => StartThread("first", "a.xlsm")); 
      thread1.Start(); 
      var thread2 = new Thread(() => StartThread("second", "b.xlsm")); 
      thread2.Start(); 
     } 
    } 
} 
+0

Questo non dovrebbe essere il problema. L'OP sta creando un 'MemorySteam' in ciascun thread e accede solo da quel thread. – Trisped