假设我们想要显示一个对话框,当 task1
中出现异常时,我们从该对话框调用一个方法,该方法启动一个新的 task2
。问题是所有者窗口在 task2
期间卡住。
请看一下简单的代码( Task Parallel Library 使用):
private void button1_Click(object sender, RoutedEventArgs e)
{
var scheduler = TaskScheduler.FromCurrentSynchronizationContext();
Task.Factory.StartNew
(() => SomeHardMethod(1)).ContinueWith(TaskContinuation, scheduler);
}
private void TaskContinuation(Task parentTask)
{
if (parentTask.IsFaulted)
{
// If we get an exception - show a dialog that starts a new task
var dlg = new WindowDialog();
var scheduler = TaskScheduler.FromCurrentSynchronizationContext();
if (dlg.Show())
{
//Here we start a new task
Task.Factory.StartNew
(() => SomeHardMethod(2)).ContinueWith(TaskContinuation, scheduler);
}
var ex = parentTask.Exception;
}
}
private void SomeHardMethod(int mode)
{
if (mode == 1)
{
throw new ArgumentException("mode");
}
else
{ //Any long operation...
Thread.Sleep(3000);
}
}
对我来说,奇怪的是,当我第一次在 button1_Click
方法中启动任务时,它不在 UI 中执行,但是当我第二次启动新任务时,它在 UI 线程中执行,所以这就是为什么所有者窗口卡住。
有人能澄清为什么这部分代码实际上不在后台启动任务吗?
if (dlg.Show())
{
//Here we start a new task
Task.Factory.StartNew
(() => SomeHardMethod(2)).ContinueWith(TaskContinuation, scheduler);
}
最佳答案
当您使用 Task.Factory.StartNew()
启动 Task
时,current scheduler用来。这意味着,如果您以这种方式从在 UI 线程上执行的 Task
启动一个 Task
,它也将在 UI 线程上执行。但是,如果您从 UI 线程但在 Task
之外(例如在事件处理程序中)启动 Task
,则不会发生同样的情况。
为了确保Task
在后台线程上执行,您需要明确指定您要使用TaskScheduler.Default
.
关于c# - 显示对话框后启动时任务卡住 UI,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16497158/