抛出错误的异常

时间:2019-07-02 11:12:46

标签: c# winforms

我有一个充当进度表的表单,并且执行以下任务:

protected override void OnShown(object sender, EventArgs e)
{
    try
    {
        await Task.Run(() =>
        {
            //Run task here...
        });
    }
    catch (OperationCanceledException oex)
    { }
    catch
    { 
        throw;
    }
    finally
    {
        Close();
    }
}

调用方法是:

try
{
    using (var progress = new ProgressForm(() =>
    {
        //The task to run async...
    }))
    {
        progress.ShowDialog();
    };
}
catch (MyCustomException cex)
{ }
catch (Exception ex)
{ }

该任务引发了MyCustomException,因此进度表仅将其抛出。但是,回到调用方法后,此异常未捕获(捕获在catch (Exception ex)块中,因为它从进度表中获取的异常是TargetInvocationException,而其InnerException是类型MyCustomException

为什么会发生这种情况,有没有办法确保从进度表中抛出的MyCustomException照原样到达调用方法?

2 个答案:

答案 0 :(得分:1)

这对我有用:

try
{
    await Task.Run(() =>
    {
        //Run task here...
    });
}
catch (AggregateException ex)
{
    foreach (Exception inner in ex.InnerExceptions)
    {
         if (inner is MyCustomException)
         {
             //todo smt..
             throw inner;
         }
    }
}

答案 1 :(得分:0)

也许您可以以显示async的方式来实现ProgressForm并等待它。 一个示例实现可能看起来像这样:

public class ProgressForm : Form
{
    private ProgressForm()
    {
    }

    public static async Task ShowAsync(Form owner, Action<IProgress<(string Message, int Progress)>> action)
    {
        owner.Enabled = false;
        try
        {
            using (var frm = new ProgressForm { StartPosition = FormStartPosition.CenterParent })
            {
                frm.Show(owner);

                try
                {
                    var progress = new Progress<(string Message, int Progress)>(frm.OnProgress);
                    await Task.Run(() => action(progress));
                }
                finally
                {
                    frm.Close();
                }
            }
        }
        finally
        {
            owner.Enabled = true;
        }
    }

    private void OnProgress((string Message, int Progress) args)
    {
        // Report progress to this ProgressForm here.
        // This line is only for demonstration. Please add controls to the form.
        this.Text = $@"{args.Message} {args.Progress}%";
    }
}

请记住,这将调用Show而不是ShowDialog。所有者被禁用,因此其行为类似于模式形式(仅适用于该父母!)。

的使用可能类似于:

private async void button1_Click(object sender, EventArgs e)
{
    void DoSomeWork(IProgress<(string Message, int Progress)> progress = null)
    {
        var loops = 5;
        for (var i = 0; i < loops; ++i)
        {
            progress?.Report(($"Loop {i + 1}", (i + 1) * 100 / loops));
            Thread.Sleep(500);
        }

        throw new DivideByZeroException("...");
    }

    try
    {
        await ProgressForm.ShowAsync(this, DoSomeWork);
    }
    catch (DivideByZeroException)
    {
        MessageBox.Show("Yeah...");
    }
}

希望有帮助。

此代码在Thread.Sleep中执行Task.Run!这只是一个演示,我需要一个耗时的示例。