有人可以解释为什么SecondTask和load事件没有根据此代码更新UI吗?
public Task First()
{
return Task.Run(
() =>
{
Task.Delay(4000);
Dispatcher.Invoke(() =>
{
Title = "From First()";
});
});
}
public Task Second()
{
return Task.Run(
() =>
{
Task.Delay(5000);
Dispatcher.Invoke(() =>
{
Title = "From Second()";
});
Task.WaitAny(First());
});
}
private void ParentWindow_Loaded(object sender, RoutedEventArgs e)
{
Second();
Title = "From Event";
}
当我运行此代码时,由于调用First(),只有表单的标题只会更改一次。
没有其他任何执行(至少从我能看到的,我可以看到达到了断点)。
我还尝试使用Task.WhenAny(First());
代替Task.WaitAny(First());
答案 0 :(得分:3)
问题是没有等待Task.Delay
。 Task.Delay
是异步睡眠,因此它会立即返回,如果您想在延迟后实际继续执行,则需要await
它。
因此,方法Second()
中发生的是lambda表达式在后台线程上执行。调用Task.Delay(5000)
时,调用会立即返回,因为未等待,Title
将设置为From Second()
。
public Task Second()
{
return Task.Run(
() =>
{
Task.Delay(5000); // need to await here
Dispatcher.Invoke(() =>
{
Title = "From Second()";
});
Task.WaitAny(First());
});
}
然后调用 First()
,因为还没有等待Task.Delay(4000)
,它会立即将Title
设置为From First()
。因此,最终结果是您只会看到From First()
。
public Task First()
{
return Task.Run(
() =>
{
Task.Delay(4000); // need to await here
Dispatcher.Invoke(() =>
{
Title = "From First()";
});
});
}
您可能还希望await
在事件处理程序中调用Second()
,除非您打算先将标题设置为From Event
,然后使用{{1}的结果覆盖它}}
Second()
答案 1 :(得分:1)
首先,您需要了解有关任务的编程。请阅读my curation上的文章。
执行任务,你不要等他们完成任务。
async-await
可以轻松完成异步工作,因此,您不应该将UI与非UI代码混合使用。试试这个:
public async Task FirstAsync()
{
await Task.Delay(4000);
Title = "From First()";
}
public async Task SecondAsync()
{
await Task.Delay(5000);
Title = "From Second()";
await FirstAsync();
}
private async void ParentWindow_Loaded(object sender, RoutedEventArgs e)
{
await SecondAsync();
Title = "From Event";
}
这可以做你想要的,而且代码更清晰。