为什么是方法?调用生成未处理的异常?即使使用TargetInvocationException也无法捕获



我正在尝试使用方法。调用窗体对话框,让用户执行一些选择/交互并继续执行。这个调用发生在异步方法中。

当一切正常工作时,如果在windows窗体上发生错误,则抛出一个未处理的异常,即使在试图捕获TargetInvocationException或只是 exception 时也是如此。

两个表单都在同一个winforms项目中。我意识到还有其他方法可以执行异步调用,但这只是为了说明这个问题。

表单对话框如下:

public partial class FakeDialog : Form
{
    public FakeDialog()
    {
        InitializeComponent();
    }
    private void btnOK_Click(object sender, EventArgs e)
    {
        throw new Exception("oh noes!");
        this.DialogResult = DialogResult.OK;
        this.Close();
    }
    private void btnCancel_Click(object sender, EventArgs e)
    {
        this.DialogResult = DialogResult.Cancel;
        this.Close();
    }
    public new DialogResult ShowDialog()
    {
        base.ShowDialog();
        return this.DialogResult;
    }
}

这是呼叫代码。如果正在执行catch块,即使在不调试时也没有(我的问题不是在这里提到的IDE中调试异常)。以下语句将导致一个未处理的异常)

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }
    private void Form1_Load(object sender, EventArgs e)
    {
        MethodInvoker simpleDelegate = new MethodInvoker(InvokeForm);
        IAsyncResult tag = simpleDelegate.BeginInvoke(null, null);
        simpleDelegate.EndInvoke(tag);
        MessageBox.Show("All done");
    }
    private void InvokeForm()
    {
        try
        {
            Type t = typeof(FakeDialog);
            MethodInfo showDialogMethod = t.GetMethod("ShowDialog", new Type[] { });
            object dialog = Activator.CreateInstance(t);
            System.Windows.Forms.DialogResult result = (System.Windows.Forms.DialogResult)showDialogMethod.Invoke(dialog, new object[] { });
            MessageBox.Show(result.ToString());
        }            
        catch (TargetInvocationException tie)
        {
            MessageBox.Show("Tie exception");
        }
        catch (Exception ex)
        {
            MessageBox.Show("general exception");
        }
    }
}

更新:

奇怪的是,我能够在运行调试时捕获异常(我确信IDE在这里有所帮助)。没有调试就运行会导致未处理的异常。

同样,通过异步调用调用似乎没有什么不同。如果我只是调用InvokeForm()(忽略所有的methodInvoker的东西),我可以达到相同的结果。

使用Visual Studio 2008在。net 2.0上运行

好的,我明白了。

代码的结果是未处理的异常。在使用Method时。在另一个类中调用一个简单方法可以正常运行,但是环境会随着表单中发生异常的源而变化。表单事件。我最终在微软支持上发现,Windows窗体事件中未处理的异常不会向上传播调用堆栈。这里有一些非常有趣的原因("Windows窗体应用程序有一个顶级异常处理程序,如果它可以恢复,则允许程序继续运行")。

这也证实了Marc提到的在Load事件中放置东西。叹息。所以这一切的原因现在很明显了。

至于在调试时运行良好的代码(与没有调试时相反),我认为我可以感谢JIT调试器。@fluf向我指出,专门启用JIT调试器的结果与使用调试器运行的结果相同。@Marc Gravell,根据VS设置,这可能解释了只有I和fluf可以繁殖。这里有更多的信息,但它不是一个生产修复。

所以真正的解决方案是要么在事件处理程序中处理异常,要么使用上面Microsoft Support文章中提到的解决方案,这解决了我的问题。

我实际上不能从你的代码中再现,但是:Load事件是....不同的,如果在Load事件中出现异常,可能会发生一些奇怪的事情。简单地说,我的建议是:将此代码移出Load事件。在这里附加调试器改变行为(Heisenbug)也没有帮助。

没有看到MethodInvoker的声明,我只能猜测,但有可能InvokeForm()方法在非ui线程上执行。

MethodInvoker simpleDelegate = new MethodInvoker(InvokeForm); 
IAsyncResult tag = simpleDelegate.BeginInvoke(null, null); 

显示一个对话框,你可以考虑这样重写:

Action simpleDelegate = new Action(InvokeForm); 
this.BeginInvoke(simpleDelegate);

相关内容

  • 没有找到相关文章

最新更新