我有一个进度表,可以用来异步执行传递给它的任务。基本上,表单的整个代码是:
public ProgressForm(IEnumerable<KeyValuePair<string, Action>> tasks)
{
InitializeComponent();
this.tasks = tasks;
}
protected override void OnShown(EventArgs e)
{
base.OnShown(e);
PerformTasks(tasks);
}
private async void PerformTasks(IEnumerable<KeyValuePair<string, Action>> tasks)
{
tokenSource = new CancellationTokenSource();
var token = tokenSource.Token;
try
{
await Task.Run(() =>
{
foreach (var task in tasks)
{
token.ThrowIfCancellationRequested();
task.Value();
}
}, token);
isTaskCompleted = true;
}
catch (OperationCanceledException oex) when (oex.CancellationToken == token)
{ }
catch
{
throw;
}
finally
{
tokenSource.Dispose();
DialogResult = isTaskCompleted ? DialogResult.OK : DialogResult.Cancel;
Close();
}
}
然后,我使用以下任务调用表单:
try
{
using (var progress = new ProgressForm(() =>
{
SomeLongRunningTask();
}))
{
progress.ShowDialog();
};
}
catch (MyException ex)
{
//Do something
}
SomeLongRunningTask
引发类型为MyException
的异常。而不是被封闭的try/catch
块捕获,而是被主线程的异常处理捕获:
[STAThread]
static void Main()
{
Application.ThreadException += new ThreadExceptionEventHandler(Application_ThreadException);
Application.Run();
}
static void Application_ThreadException(object sender, ThreadExceptionEventArgs e)
{
//Do something
}
为什么不能在正确的位置捕获异常,如何使异常被捕获在该块中?
答案 0 :(得分:0)
您不是应该尝试抓住TaskCanceledException
吗?
在下面的示例中,它首先被捕获在最接近的try...catch
块中。
app:
using System;
using System.Threading;
using System.Windows.Forms;
namespace temp
{
internal static class Program
{
[STAThread]
private static void Main()
{
Application.ThreadException += ApplicationOnThreadException;
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
private static void ApplicationOnThreadException(object sender, ThreadExceptionEventArgs e)
{
throw new NotImplementedException();
}
}
}
表格:
using System;
using System.Media;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace temp
{
public partial class Form1 : Form
{
private readonly CancellationTokenSource _cancellationTokenSource = new CancellationTokenSource();
public Form1()
{
InitializeComponent();
var button1 = new Button {Text = "Start"};
button1.Click += Button1OnClick;
var button2 = new Button {Text = "Abort"};
button2.Click += Button2OnClick;
var panel = new FlowLayoutPanel();
panel.Controls.Add(button1);
panel.Controls.Add(button2);
Controls.Add(panel);
}
private async void Button1OnClick(object sender, EventArgs e)
{
try
{
var token = _cancellationTokenSource.Token;
await Task.Run(async () =>
{
for (var i = 0; i < 10; i++)
{
token.ThrowIfCancellationRequested();
await Task.Delay(3000, token);
SystemSounds.Beep.Play();
}
}, token);
}
catch (Exception exception)
{
Console.WriteLine(exception);
throw;
}
}
private void Button2OnClick(object sender, EventArgs e)
{
_cancellationTokenSource.Cancel();
}
}
}