【发布时间】:2017-06-11 19:50:45
【问题描述】:
我正在为DocumentViewer 生成一个文档。它很慢,所以我想释放 UI 线程。使用 async/await 我得到一个异常,“调用线程必须是 STA”。我相信我需要编组通过 UI 线程传递/返回的值,但我似乎无法使其工作。我以各种方式尝试过 Dispatcher.Invoke。
有人知道如何使用 async/await 来做到这一点吗?
这是一个可以粘贴到新的 WPF 项目 (WpfApp1) 中的苗条的工作示例:
<Window x:Class="WpfApp1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApp1"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525"
DataContext="{Binding RelativeSource={RelativeSource Self}}">
<DocumentViewer Document="{Binding Document}"/>
</Window>
public partial class MainWindow : Window, INotifyPropertyChanged
{
public MainWindow()
{
InitializeComponent();
RebuildDocument(); // Called various places
}
public double Length { get; set; } = 100;
FixedDocument document;
public FixedDocument Document
{
get { return document; }
set { if (document == value) return; document = value; OnPropertyChanged(); }
}
async void RebuildDocument()
{
Document = await GenerateDocument(Length);
}
private static async Task<FixedDocument> GenerateDocument(double length)
{
return await Task.Run(() =>
{
// Dummy work
return new FixedDocument() {
Pages = { new PageContent() { Child = new FixedPage() {
Width = length, Height = length,
Children = { new TextBlock() { Text = "dummy page" }}}}}};
});
}
public event PropertyChangedEventHandler PropertyChanged;
void OnPropertyChanged([CallerMemberName] string propertyName = null)
{ PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); }
}
【问题讨论】:
-
问题与
async/await无关。问题是GenerateDocument的主体必须在 STA 线程中运行。因为这些是正在实例化的 UI 元素。尝试使用 MVVM 方法。
标签: wpf async-await