文章出處

  我碰到這個問題比較奇怪,我寫的一個方法(基于.NET 2.0)在win7、win2003下運行沒有問題,在winxp下運行就拋異常:“公共語言運行時檢測到無效的程序”,對應英文為:common language runtime detected an invalid program.

  拋異常的方法代碼摘抄如下:

    private Control control = ...;
    public void ActionOnUI<T1>(bool showMessageBoxOnException, bool beginInvoke,  CbGeneric<T1> method, params object[] args)
    {
        if (this.control.InvokeRequired)
        {
            if (beginInvoke)
            {
                this.control.BeginInvoke(new CbGeneric<bool, bool, CbGeneric<T1>, object[]>(this.ActionOnUI), showMessageBoxOnException, beginInvoke, method, args);
            }
            else
            {
                this.control.Invoke(new CbGeneric<bool, bool, CbGeneric<T1>, object[]>(this.ActionOnUI), showMessageBoxOnException, beginInvoke, method, args);
            }
        }
        else
        {
            try
            {
                method((T1)args[0]);
            }
            catch (Exception ee)
            {                if (showMessageBoxOnException)
                {
                    MessageBox.Show(ee.Message);
                }
            }
        }
    }

    方法的目的是對UI調用轉發做一個封裝,讓使用者更方便的將調用轉發到UI線程。

    但是,這個方法在執行時,異常在xp下發生了:

     Common Language Runtime detected an invalid program.

          at ESBasic.Helpers.UiSafeInvoker.ActionOnUI[T1](Boolean showMessageBoxOnException, Boolean beginInvoke, CbGeneric`1 method, Object[] args)

     我在網上搜了一些相關問題的解答,比較靠譜的一點是這樣說的:

    “這種錯誤非常少見,是一個編譯器錯誤,通常產生在將C#等托管語言生成為MSIL時候出的錯,沒有什么好的解決辦法,現在可行的方法好像就是修改現在的程序結構,這樣根據新的結構生成新的MSIL時不會出錯就基本可以避免這個問題。”

    根據這個提示,我對方法的代碼進行了各種修改嘗試,最后終于得到了一種在xp下也不拋異常的結構,粘貼如下:

    private Control control = ...;
    public void ActionOnUI<T1>(bool showMessageBoxOnException, bool beginInvoke, CbGeneric<T1> method, T1 args)
    {
        if (this.control.InvokeRequired)
        {
            if (beginInvoke)
            {
                this.control.BeginInvoke(new CbGeneric<bool, CbGeneric<T1>, T1>(this.Do_ActionOnUI<T1>), showMessageBoxOnException, method, args);
                return;
            }
            this.control.Invoke(new CbGeneric<bool, CbGeneric<T1>, T1>(this.Do_ActionOnUI<T1>), showMessageBoxOnException, method, args);
            return;
        }

        this.Do_ActionOnUI<T1>(showMessageBoxOnException, method, args);
    }

    private void Do_ActionOnUI<T1>(bool showMessageBoxOnException, CbGeneric<T1> method, T1 args)
    {
        try
        {
            method(args);
        }
        catch (Exception ee)
        {            if (showMessageBoxOnException)
            {
                MessageBox.Show(ee.Message);
            }
        }
    } 

  總結起來,改變的幾點如下:

(1)將真正執行的部分重構為一個方法Do_ActionOnUI,然后,轉發調用Invoke都指向這個方法。

(2)Invoke轉發調用時,為指向的方法加上泛型參數,避免編譯器自動去匹配。

(3)將弱類型的參數object[]修改為強類型的參數T1。

  好吧,現在問題總算是解決了,好好折騰了一番啊~~

 

 


文章列表




Avast logo

Avast 防毒軟體已檢查此封電子郵件的病毒。
www.avast.com


arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()