2012-08-25 83 views
1

我有這樣的代碼首先構造和按鈕單擊事件:爲什麼我收到異常:調用的目標引發異常?

using System.Text; 
using System.Windows.Forms; 
using System.Xml; 
using System.Xml.Linq; 
using System.Xml.XPath; 
using System.IO; 
using System.Collections; 

namespace WindowsFormsApplication1 
{ 
    public partial class Form1 : Form 
    { 
     DirectoryInfo dirinf = new DirectoryInfo(@"C:\"); 
     List<FileSystemInfo> fsi = new List<FileSystemInfo>(); 

     public Form1() 
     { 
      InitializeComponent(); 
     } 

     private void button1_Click(object sender, EventArgs e) 
     { 
      backgroundWorker1.RunWorkerAsync(); 
      button1.Enabled = false; 
     } 

然後,我有一個搜索功能和backgroundowrker DoWork的事件:

public void Search(string strExtension, 
          DirectoryInfo di, 
          List<FileSystemInfo> pResult) 
     { 
      try 
      { 

       foreach (FileInfo fi in di.GetFiles()) 
       { 
        if (InvokeRequired) 
        { 
         BeginInvoke(new Action(() => label2.Text = fi.Name)); 
        } 
        if (fi.Name == "MessageLog.xsl") 
        { 
         foreach (FileInfo fii in di.GetFiles()) 
         { 
         if (fii.Extension == strExtension) 
          pResult.Add(fii); 
         } 
         if (InvokeRequired) 
         { 
          BeginInvoke(new Action(() => textBox1.AppendText("Number Of History Files Found: ===> " + pResult.Count.ToString() + Environment.NewLine))); 
         } 

        } 
       } 

        foreach (DirectoryInfo diChild in di.GetDirectories()) 
         Search(strExtension, diChild, pResult); 

      } 
      catch (Exception e) 
      { 
      } 
     } 

     private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) 
     { 
      Search(".xml", dirinf, fsi); 
      for (int i = 0; i < fsi.Count; i++) 
      { 
       if (InvokeRequired) 
       { 
        BeginInvoke(new Action(() => textBox1.AppendText(fsi[i - 1].FullName + Environment.NewLine))); 
       } 

      } 
     } 

當其獲得的部分在DoWork的事件:

for (int i = 0; i < fsi.Count; i++) 
       { 
        if (InvokeRequired) 
        { 
         BeginInvoke(new Action(() => textBox1.AppendText(fsi[i - 1].FullName + Environment.NewLine))); 
        } 

       } 

經過一個或兩個itertions其拋出的異常在Program.cs中上線:

Application.Run(new Form1()); 

異常被拋出由調用

解決它的目標通過向BackgroundWorker的完成事件報告:

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) 
     { 
      Search(".xml", dirinf, fsi); 
      backgroundWorker1.ReportProgress(100); 

     } 

     private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
     { 
      for (int i = 0; i < fsi.Count; i++) 
      {     
        textBox1.AppendText(fsi[i].FullName + Environment.NewLine); 
      } 
     } 

工作剛剛好。

+1

我懷疑的原因是你調用BeginInvoke的一個循環中。首先構建字符串並在循環後調用BeginInvoke。 – mbm

+0

mbm我通過將循環移動到backgroundworker的完成事件來解決它。謝謝。 –

回答

2

你已經解決了這個問題(正確的,這應該在Completed事件中完成)。

剩下的就是一個解釋:

您使用的是可變i,也就是本地的DoWork的方法,操作拉姆達內。這意味着所有代碼都使用1個共享(盒裝)版本的變量。它被稱爲'關閉循環var'。

症狀符合:當第二個或第三個開始執行主循環時,lambda表達式已執行異步,已經執行i == fsi.Count。 (內部)異常應該是「索引超出範圍」。

for (int i = 0; i < fsi.Count; i++) 
{ 
    if (InvokeRequired) 
    { 
     BeginInvoke(new Action(() => 
      textBox1.AppendText(fsi[i - 1].FullName // captured 'i' 
      + Environment.NewLine))); 
    } 
} 

它可以固定這樣:

for (int i = 0; i < fsi.Count; i++) 
{ 
    if (InvokeRequired) 
    { 
     int iCopy = i;  // 1 instance per loop 

     BeginInvoke(new Action(() => 
      textBox1.AppendText(fsi[iCopy - 1].FullName 
      + Environment.NewLine))); 
    } 
} 
相關問題