2008-10-21 44 views
1

当我写这需要一个通用的参数变量的大型静态方法。我调用这个方法,并且框架抛出一个System.InvalidProgramException异常。甚至在方法的第一行执行之前抛出此异常。“CLR检测到无效的程序。”调用泛型方法

我可以创建一个静态类,它采用了通用的参数,然后使这个静态类的方法,和一切工作正常。

这是一个.NET的缺陷,或者是有我打破这里一些不起眼的通用规则?

为了完整起见,我已经包括该失败的方法,并且其传递方法。请注意,这里使用了一些其他类的从我自己的库(如GridUtils),并且这些类在此不再赘述。我不认为实际意义的问题:问题是为什么运行时崩溃的方法,甚至开始之前。

这将引发异常(我与Visual Studio 2005编程,所以也许这已经在Visual Studio 2008中消失)的第一行调用之前:

private delegate void PROG_Delegate<TGridLine>(DataGridView dgv, IEnumerable<TGridLine> gridLines, string[] columns); 

    public static void PopulateReadOnlyGrid<TGridLine>(DataGridView dgv, IEnumerable<TGridLine> gridLines, string[] columns) 
    { 
     if (dgv.InvokeRequired) 
     { 
      dgv.BeginInvoke 
         (
          new PROG_Delegate<TGridLine>(PopulateReadOnlyGrid<TGridLine>), 
          new object[] { dgv, gridLines, columns } 
         ); 
      return; 
     } 
     GridUtils.StatePreserver statePreserver = new GridUtils.StatePreserver(dgv); 
     System.Data.DataTable dt = CollectionHelper.ConvertToDataTable<TGridLine>((gridLines)); 
     dgv.DataSource = dt; 
     dgv.DataMember = ""; 
     dgv.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells; 
     GridUtils.OrderColumns<TGridLine>(dgv, columns); 
     statePreserver.RestoreState(); 
     dgv.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.None; 
    } 

这工作得很好:

public static class Populator<TGridLine> 
    { 
     private delegate void PROG_Delegate(DataGridView dgv, IEnumerable<TGridLine> gridLines, string[] columns); 

     public static void PopulateReadOnlyGrid(DataGridView dgv, IEnumerable<TGridLine> gridLines, string[] columns) 
     { 
      if (dgv.InvokeRequired) 
      { 
       dgv.BeginInvoke 
          (
           new PROG_Delegate(PopulateReadOnlyGrid), 
           new object[] { dgv, gridLines, columns } 
          ); 
       return; 
      } 
      GridUtils.StatePreserver statePreserver = new GridUtils.StatePreserver(dgv); 
      System.Data.DataTable dt = CollectionHelper.ConvertToDataTable<TGridLine>((gridLines)); 
      dgv.DataSource = dt; 
      dgv.DataMember = ""; 
      dgv.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells; 
      GridUtils.OrderColumns<TGridLine>(dgv, columns); 
      statePreserver.RestoreState(); 
      dgv.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.None; 

     } 
    }   
+0

这是用于ASP.NET,WinForms还是什么?什么是GridUtils命名空间? – GregUzelac 2008-10-21 02:03:58

+0

GridUtils命名空间是我自己的库的一部分。我会澄清它的消息,谢谢。 – 2008-10-21 02:05:05

回答

0

仅供参考,不知道这是否会解决任何事情,b你的Invoke方法可以简化。这也消除了该委托的需求(可能导致修复?):

dgv.BeginInvoke(new MethodInvoker(delegate() 
{ 
    PopulateReadOnlyGrid(dgv, gridLines, columns); 
})); 

你的代码运行对我很好,当我将其粘贴到表(后注释掉你GridUtils的东西)。我甚至从gui线程和非gui线程调用这个方法。我在3.5和2.0中试过了。做工精细....

试试这个代码(!?):

using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Data; 
using System.Drawing; 
using System.Text; 
using System.Windows.Forms; 
using System.Reflection; 
using System.Threading; 

namespace WindowsFormsApplication1 
{ 
    public partial class Form1 : Form 
    { 
     public Form1() 
     { 
      InitializeComponent(); 
     } 

     private delegate void PROG_Delegate<TGridLine>(Control dgv, IEnumerable<TGridLine> gridLines, string[] columns); 

     public static void PopulateReadOnlyGrid<TGridLine>(Control dgv, IEnumerable<TGridLine> gridLines, string[] columns) 
     { 
      if (dgv.InvokeRequired) 
      { 
       dgv.BeginInvoke 
          (
           new PROG_Delegate<TGridLine>(PopulateReadOnlyGrid<TGridLine>), 
           new object[] { dgv, gridLines, columns } 
          ); 
       return; 
      } 
      MessageBox.Show("hi"); 
      //GridUtils.StatePreserver statePreserver = new GridUtils.StatePreserver(dgv); 
      //System.Data.DataTable dt = CollectionHelper.ConvertToDataTable<TGridLine>((gridLines)); 
      //dgv.DataSource = dt; 
      //dgv.DataMember = ""; 
      //dgv.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells; 
      //GridUtils.OrderColumns<TGridLine>(dgv, columns); 
      //statePreserver.RestoreState(); 
      //dgv.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.None; 
     } 

     private void button1_Click(object sender, EventArgs e) 
     { 
      PopulateReadOnlyGrid(this, new int[] { 1, 2, 3 }, new string[] { "a" }); 

      ThreadPool.QueueUserWorkItem(new WaitCallback((a) => 
      { 
       PopulateReadOnlyGrid(this, new int[] { 1, 2, 3 }, new string[] { "a" }); 
      })); 

     } 

    } 
} 
0

TheSoftwareJedi's建议,我进行了一些测试,最终证实它的使用导致异常的PROG_Delegate的。

如果我使用MethodInvoker,代码运行时没有错误。

private delegate void PROG_Delegate<TGridLine>(DataGridView dgv, IEnumerable<TGridLine> gridLines, string[] columns); 

    public static void PopulateReadOnlyGrid<TGridLine>(DataGridView dgv, IEnumerable<TGridLine> gridLines, string[] columns) 
    { 
     if (dgv.InvokeRequired) 
     { 
      dgv.BeginInvoke(new MethodInvoker(delegate() 
      { 
       PopulateReadOnlyGrid(dgv, gridLines, columns); 
      })); 
      return; 
     } 
     GridUtils.StatePreserver statePreserver = new GridUtils.StatePreserver(dgv); 
     System.Data.DataTable dt = CollectionHelper.ConvertToDataTable<TGridLine>((gridLines)); 
     dgv.DataSource = dt; 
     dgv.DataMember = ""; 
     dgv.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells; 
     GridUtils.OrderColumns<TGridLine>(dgv, columns); 
     statePreserver.RestoreState(); 
     dgv.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.None; 
    } 

如果我把PROG_Delegate回并删除一切我得到的异常了。

private delegate void PROG_Delegate<TGridLine>(DataGridView dgv, IEnumerable<TGridLine> gridLines, string[] columns); 

    public static void PopulateReadOnlyGrid<TGridLine>(DataGridView dgv, IEnumerable<TGridLine> gridLines, string[] columns) 
    { 
     if (dgv.InvokeRequired) 
     { 
      dgv.BeginInvoke 
         (
          new PROG_Delegate<TGridLine>(PopulateReadOnlyGrid<TGridLine>), 
          new object[] { dgv, gridLines, columns } 
         ); 
     } 
     //GridUtils.StatePreserver statePreserver = new GridUtils.StatePreserver(dgv); 
     //System.Data.DataTable dt = CollectionHelper.ConvertToDataTable<TGridLine>((gridLines)); 
     //dgv.DataSource = dt; 
     //dgv.DataMember = ""; 
     //dgv.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells; 
     //GridUtils.OrderColumns<TGridLine>(dgv, columns); 
     //statePreserver.RestoreState(); 
     //dgv.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.None; 
    } 

因此,有一个简单的解决方法,MethodInvoker的使用使代码更加简洁和可读。

从理论上讲,还是有,为什么它的崩溃问题,鉴于PROG_Delegate是合法的,它的工作的其他人。我怀疑我们可以得出的最佳答案是“一些不明确的错误”,因为编码人员总是喜欢使用方法调用器,所以这仍然是模糊的。