2013-05-10 158 views
0

我構建了一個程序,用於搜索由用戶(源文件夾)設置的文件夾內的所有.xml,並將所有這些文件複製到另一個文件夾(目標文件夾)。處理多個txt文件時出錯

Form1

我的方案是能夠搜索所有子文件夾中的所有XML從(來源文件夾),5000頁左右的文件結果返回第一個被放置在列表,這個列表後來被一個函數的工作,但他只能使用31個文件,然後出現「不響應」,調試器顯示該程序在執行中保持很長時間。

這裏是我的代碼:

按鈕動作:

private void btnCopiarSalvar_Click(object sender, EventArgs e) 
{ 
    foreach (string name in listFileNames) 
    { 
     if (readXML(name)) 
     { 
       tbArquivo.Text = name ; //Feedback textbox, tell the current filename 
     }      
    } 
    pbStatus.Increment(50); 
    cbFinal.Checked = true; //Feedback checkBox, to tell user that the task is over. 
} 

功能ReadXML的

public bool readXML(string name) 
{ 
    //foreach (string nome in listaArquivos) 
    //{ //I tried to the foreach inside, but nothing Works. 

    try 
    { 
     string text = null; 
     string readBuffer = File.ReadAllText(name); 
     text = readBuffer.Aggregate(text, (current, b) => current + b); 
     var encoding = new ASCIIEncoding(); 
     Byte[] textobytes = encoding.GetBytes(text); 

     if (!File.Exists(destino)) 
     { 
      string destinoComNomeArquivo = destino + "\\" + Path.GetFileName(nome); 
      using (FileStream fs = File.Create(destinoComNomeArquivo)) 
      { 
       foreach (byte textobyte in textobytes) 
       { 
        fs.WriteByte(textobyte); 
        pbProcess.PerformStep(); 
       } 
       Console.WriteLine("Arquivo gravado " + Path.GetFileName(nome)); 
      } 
     } 
     pbProcess.PerformStep(); 
    } 
    catch (Exception e) 
    { 
     Console.WriteLine(e); 
    } 
    //} 
    return true; 
} 

錯誤:檢測ContextSwitchDeadlock。

嘗試解決方案:禁用託管調試助手。

禁用MDA後,程序仍然只讀取31個文件(5k)。

+0

等待20分鐘後,我現在有127個.XML文件,所以我想我只是有等待......但我太沉重了,即使是英特爾i7。 – 2013-05-10 22:12:27

+0

我可以使用File.copy來複制所有文件,但是我需要在文件末尾讀寫信息。所以我需要閱讀所有文件...悲傷。 – 2013-05-10 22:16:42

+2

正如其他人所建議的那樣,使用'File.Copy'方法複製文件,讀取整個文件並將其寫入不同的文件效率極低。至於等待的問題,這是因爲讀/寫操作正在GUI上運行的同一線程上執行。把它放在一個'BackgroundWorker'中,讓它做好工作並更新進度條。 – PoweredByOrange 2013-05-10 22:18:30

回答

1

我推薦的第一件事是......不要做那種文件拷貝!改用File.Copy函數。

嘗試使用此代碼MSDN剪斷:

void DoCopy(string path) 
{ 
    var copytask = new Task(() => 
    { 
     string destinoComNomeArquivo = @"C:\" + Path.GetFileName(path); 
     DirectoryCopy(path, destinoComNomeArquivo, false); 
    }); 
    copytask.Start(); 
} 

private void DirectoryCopy(string sourceDirName, string destDirName, bool copySubDirs) 
{ 
    DirectoryInfo dir = new DirectoryInfo(sourceDirName); 
    DirectoryInfo[] dirs = dir.GetDirectories(); 

    if (!dir.Exists) 
    { 
     throw new DirectoryNotFoundException(
      "Source directory does not exist or could not be found: " 
      + sourceDirName); 
    } 

    if (!Directory.Exists(destDirName)) 
    { 
     Directory.CreateDirectory(destDirName); 
    } 

    FileInfo[] files = dir.GetFiles(); 
    foreach (FileInfo file in files) 
    { 
     string temppath = Path.Combine(destDirName, file.Name); 
     file.CopyTo(temppath, false);     
    } 

    var counter = 0; 
    var maxcounter = files.Count(); 

    while (maxcounter < counter) 
    { 
     var item = files.ElementAt(counter).Name; 
     WriteAsnc(item); 
     counter++; 
    } 

    if (copySubDirs) 
    { 
     foreach (DirectoryInfo subdir in dirs) 
     { 
      string temppath = Path.Combine(destDirName, subdir.Name); 
      DirectoryCopy(subdir.FullName, temppath, copySubDirs); 
     } 
    } 
} 

const int _maxwritingprocess = Environment.ProcessorCount; 
int _currentwritingtasks; 

void WriteAsnc(string filepath) 
{ 
    _currentwritingtasks++; 
    var task = Task.Factory.StartNew(() => 
    { 
     XDocument doc = XDocument.Load(filepath); 
     doc.Elements().First().Add(new XAttribute("Attribute Name","Attribute Value")); 
     doc.Save(filepath); 
     _currentwritingtasks--; 
    }); 
    if(_currentwritingtasks == _maxwritingprocess) 
     task.Wait(); 
    _currentwritingtasks--; 
} 

下一個點ContextSwitchDeadlock是一個線程的問題,我的事情你pbProcess是源。這個過程是什麼我沒有看到這個過程的任何事情,我不喜歡它是無效的爲您的副本

+0

最大的問題是:我仍然需要在XML文件中寫東西,但現在我要使用Backgroundworker來完成任務。 – 2013-05-11 00:03:28

+0

此解決方案使用更高效的[任務](http://msdn.microsoft.com/en-us/library/system.threading.tasks.task.aspx),並建議使用後臺操作(我將添加一個稍後參考討論)。該解決方案將枚舉目錄中的所有文件並將它們移動到新的文件中。該操作後,它會打開所有文件,寫自己的XML屬性的,這種happeds allso線程,所以你可以控制你的表現比maxwritingprocess變量,以獲得最佳的性能爲您的PC – Venson 2013-05-11 00:09:20

+0

[使用任務,而不是BackgroundWorker的(HTTP:/ /msdn.microsoft.com/en-us/library/vstudio/hh191443.aspx) – Venson 2013-05-11 00:16:21