我有一个充当进度表的表单,并且执行以下任务:
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
照原样到达调用方法?
答案 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
!这只是一个演示,我需要一个耗时的示例。