C# 如何在没有块 UI 的情况下使用等待捕获任务中的异常
C# How to catch exception in a Task without block UI using wait
我在单击按钮时有此代码
private async void btnStart_Click(object sender, EventArgs e)
{
Msg.Clear();
stopWatch.Reset();
timer.Start();
stopWatch.Start();
lblTime.Text = stopWatch.Elapsed.TotalSeconds.ToString("#");
progressBar.MarqueeAnimationSpeed = 30;
try
{
await Task.Factory.StartNew(() =>
{
try
{
Reprocess();
}
catch (Exception ex)
{
Msg.Add(new clsMSG(ex.Message, "Error", DateTime.Now));
timer.Stop();
stopWatch.Stop();
throw;
}
});
}
catch
{
throw;
}
}
以及 Reprocess 方法
private void Reprocess()
{
try
{
clsReprocess reprocess = new clsReprocess(tbBD.Text, dtpStart.Value, 50000);
reprocess.Start(reprocess.BD);
}
catch
{
throw;
}
}
Reprocess方法失败时,Task去catch,但是throw失败(throw inside catch(Exception ex)),UI阻塞,直到reprocess.Start方法完成。
我有两个问题:
- 第一:我怎样才能在按钮的接球中接球?
- 其次:如何防止UI块?
希望你能理解我,抱歉我的英语不好。
你不应该使用 Task.Factory.StartNew
; Task.Run
写起来既安全又短。
此外,您只能从 UI 线程访问 UI 控件。如果 Msg
数据绑定到 UI,这可能是您所看到的问题的原因。即使不是,您也不想从多个线程访问不受保护的集合(例如,List<clsMSG>
)。
同时应用这两个准则可将代码缩减为:
private async void btnStart_Click(object sender, EventArgs e)
{
Msg.Clear();
stopWatch.Reset();
timer.Start();
stopWatch.Start();
lblTime.Text = stopWatch.Elapsed.TotalSeconds.ToString("#");
progressBar.MarqueeAnimationSpeed = 30;
try
{
await Task.Run(() => Reprocess());
}
catch (Exception ex)
{
Msg.Add(new clsMSG(ex.Message, "Error", DateTime.Now));
timer.Stop();
stopWatch.Stop();
throw;
}
}
如果 Reprocess
抛出异常,该异常将被放置在从 Task.Run
返回的任务中。当您的代码 await
执行该任务时,该异常会重新引发并在 catch
中捕获。在 catch
结束时,代码将重新引发该异常 (throw;
)。
我在单击按钮时有此代码
private async void btnStart_Click(object sender, EventArgs e)
{
Msg.Clear();
stopWatch.Reset();
timer.Start();
stopWatch.Start();
lblTime.Text = stopWatch.Elapsed.TotalSeconds.ToString("#");
progressBar.MarqueeAnimationSpeed = 30;
try
{
await Task.Factory.StartNew(() =>
{
try
{
Reprocess();
}
catch (Exception ex)
{
Msg.Add(new clsMSG(ex.Message, "Error", DateTime.Now));
timer.Stop();
stopWatch.Stop();
throw;
}
});
}
catch
{
throw;
}
}
以及 Reprocess 方法
private void Reprocess()
{
try
{
clsReprocess reprocess = new clsReprocess(tbBD.Text, dtpStart.Value, 50000);
reprocess.Start(reprocess.BD);
}
catch
{
throw;
}
}
Reprocess方法失败时,Task去catch,但是throw失败(throw inside catch(Exception ex)),UI阻塞,直到reprocess.Start方法完成。 我有两个问题:
- 第一:我怎样才能在按钮的接球中接球?
- 其次:如何防止UI块?
希望你能理解我,抱歉我的英语不好。
你不应该使用 Task.Factory.StartNew
; Task.Run
写起来既安全又短。
此外,您只能从 UI 线程访问 UI 控件。如果 Msg
数据绑定到 UI,这可能是您所看到的问题的原因。即使不是,您也不想从多个线程访问不受保护的集合(例如,List<clsMSG>
)。
同时应用这两个准则可将代码缩减为:
private async void btnStart_Click(object sender, EventArgs e)
{
Msg.Clear();
stopWatch.Reset();
timer.Start();
stopWatch.Start();
lblTime.Text = stopWatch.Elapsed.TotalSeconds.ToString("#");
progressBar.MarqueeAnimationSpeed = 30;
try
{
await Task.Run(() => Reprocess());
}
catch (Exception ex)
{
Msg.Add(new clsMSG(ex.Message, "Error", DateTime.Now));
timer.Stop();
stopWatch.Stop();
throw;
}
}
如果 Reprocess
抛出异常,该异常将被放置在从 Task.Run
返回的任务中。当您的代码 await
执行该任务时,该异常会重新引发并在 catch
中捕获。在 catch
结束时,代码将重新引发该异常 (throw;
)。