ISynchronizeInvoke中的InvalidCastException

时间:2015-04-15 08:34:25

标签: c#

我试图使用一个包含少量事件的dll文件。当我尝试使用下面的代码时,我得到:

  

"类型' System.InvalidCastException'"

的例外情况

  

"无法投射#q; qweqwe_po.MyHandler'输入   ' System.ComponentModel.ISynchronizeInvoke'"

我不知道为什么会这样,需要一些帮助。如果我在Form1或Form2中使用MyHandler中的代码,它可以正常工作,因此我猜测我的委托有问题。有人能看出我做错了吗?

故障在行(MyHandler)上触发:

((ISynchronizeInvoke)d.Target).BeginInvoke(d, new object[] { this, e });

Form1

 public partial class Form1 : Form
    {
        MyHandler obj;

        public Form1()
        {
            InitializeComponent();
            obj = new MyHandler();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            using (Form2 f = new Form2(obj, new Random().Next(20,80)+1))
            {
                f.ShowDialog();
            }
        }
    }

窗体2

public partial class Form2 : Form
{
    private MyHandler obj;

    public Form2(MyHandler p_obj, double sum)
    {
        InitializeComponent();

        obj = p_obj;
        textBox1.Text = sum.ToString();

    }
}

MyHandler的

public class MyHandler
{
    private figure fig;
    public event FigureEventHandler FigureEvent;
    private double m_Sum;

    public MyHandler()
    {
        init();
    }

    public void init()
    {
        fig = new figure();

        // PIM event
        fig.OnStatus += new IFigureEvents_OnStatusEventHandler(fig_OnStatus);
        fig.OnReturn += new IFigureEvents_OnReturnEventHandler(fig_OnReturn);
        FigureEvent += new FigureEventHandler(MainWindow_FigureEvent);


        int res = 0;
        if ((res = fig.open("192.168.16.68") != 0)
        {
            Console.WriteLine("figure.dll open failed. Error: " + res);
            return;
        }

        if ((res = fig.startConnection()) != 0)
            Console.WriteLine("Error starting com test");
    }

    public void fig_OnStatus(short statusType)
    {
        OnFigureEvent(new FigureEventArgs(integrationEvents.STATUS, statusType));
    }

    public void fig_OnReturn()
    {
        OnFigureEvent(new FigureEventArgs(integrationEvents.RESULT, 0));
    }

    protected virtual void OnFigureEvent(FigureEventArgs e)
    {
        if (FigureEvent != null)
        {
            foreach (Delegate d in FigureEvent.GetInvocationList())
                ((ISynchronizeInvoke)d.Target).BeginInvoke(d, new object[] { this, e });
        }
    }

    public void MainWindow_FigureEvent(object sender, FigureEventArgs e)
    {
        switch (e.IntegrationEvent)
        {
            case integrationEvents.STATUS:
                // status logic
            case integrationEvents.RESULT:
                //result logic
        }
    }

    public bool Send(transTypes p_TransType, double p_Value)
    {
        int res = 0;
        if (p_TransType == transTypes.TRANS_NONE || fig.Busy != 0)
            return false;

        res = fig.Send(0x30);
        if (res != 0)
            Console.WriteLine("Error calling Send(): " + res);
        return !Convert.ToBoolean(res);
    }
}

public class FigureEventArgs : EventArgs
{
    private readonly integrationEvents integrationEvent = integrationEvents.NONE;
    private readonly short statusType = 0;

    public FigureEventArgs(integrationEvents integrationEvent, short statusType)
    {
        this.integrationEvent = integrationEvent;
        this.statusType = statusType;
    }

    public integrationEvents IntegrationEvent { get { return integrationEvent; } }
    public short StatusType { get { return statusType; } }
}

public delegate void FigureEventHandler(object sender, FigureEventArgs e);
   }

1 个答案:

答案 0 :(得分:1)

你正在破坏东西。原始代码将相关控件(旧MainWindow_FigureEvent)的UI线程上的事件回调设置为marh。

foreach (Delegate d in FigureEvent.GetInvocationList())
 ((ISynchronizeInvoke)d.Target).BeginInvoke(d, new object[] { this, e });

这基本上说"将事件的调用链中添加的所有委托调用,并在"中定义它们的类的实例的线程上调用它们。

因此,如果您从与原始控件的UI线程不同的线程触发事件,则委托执行将被编组到UI线程,而不是继续执行导致事件触发的线程。

多线程很难

你必须非常小心。编写原始代码的人有理由这样做。了解原因。确保它们是否有意义。如果没有,您可以使用FigureEvent()代替for-each。但是,如果它们仍然有意义,那么你在这里尝试的所有东西都无法工作 - 你通过向{{1添加回调函数 - 抛弃了关于​​你需要编组回来的线程的信息。 }}而不是MyHandler

改变这样的事情带来大量的副作用。听起来你并不能完全处理所涉及的复杂问题,所以如果可能的话,尝试与更多经验丰富的多线程人员合作。如果不可能,请尽量保持与原始实施尽可能接近。听起来你正试图摆脱一些重复的代码。但是,很难给出任何有关如何正确处理此问题的直接指示,因为这是您未显示的代码部分。但主要的想法是不要通过像这样的Form类来处理这个问题,而是将实现的公共部分推到一个单独的类中,同时将事件处理程序保留在MyHandler上。您可能需要在这里和那里重写几个位,添加一些接口,可能是继承。

回到我们所拥有的代码摘录,请注意以下将事件处理程序移动到Form时发生的变化:

  • MyHandler不再是表格。这会导致您d.Target
  • InvalidCastException不再是表格。哎呀。您确定事件处理程序不希望this参数成为表单吗?

事实上,您完全抛弃了有关表单的信息。您正在使用的架构并不是很明显,因此我无法向您展示如何解决所有问题,但至少您应该在路上:)