我試圖進行異步調用以將數據加載到我的網格。問題是,操作阻塞了UI(在主線程中運行) - 我不知道爲什麼。我試圖讓它在後臺取數據...下面的代碼:Task.Run阻止主線程(凍結的UI)
綁定視圖模型類的DataContext主窗口:
<Window.DataContext>
<vm:MainWindowViewModel WindowTitle="MVVM" BtnLoadText="LOAD DATA"/>
</Window.DataContext>
在DataGrid中列綁定到集合屬性( PeopleList)在ViewModel類:在主窗口的
<DataGrid AutoGenerateColumns="False" IsReadOnly="True" ItemsSource="{Binding Path=PeopleList, Mode=TwoWay}" Margin="5">
<DataGrid.Columns>
<DataGridTextColumn Header="First name" Binding="{Binding Path=FirstName}"/>
<DataGridTextColumn Header="Last name" Binding="{Binding Path=LastName}"/>
<DataGridTextColumn Header="Age" Binding="{Binding Path=Age}"/>
</DataGrid.Columns>
</DataGrid>
<Button x:Name="btn_LoadData" Margin="5" Grid.Row="1" Content="{Binding Path=BtnLoadText}" Click="btn_LoadData_Click"/>
代碼隱藏 - 異步運行按鈕單擊事件:
public partial class MainWindow : Window
{
private MainWindowViewModel mainWindowViewModel;
public MainWindow()
{
InitializeComponent();
mainWindowViewModel = (MainWindowViewModel)DataContext;
}
private async void btn_LoadData_Click(object sender, RoutedEventArgs e)
{
await mainWindowViewModel.LoadData();
}
}
ViewModel類負責主窗口:
class MainWindowViewModel
{
public string WindowTitle { get; set; }
public string BtnLoadText { get; set; }
public ObservableCollection<Person> PeopleList { get; set; }
private Database database = new Database();
public MainWindowViewModel()
{
PeopleList = new ObservableCollection<Person>();
}
public async Task LoadData()
{
PeopleList.Clear();
var result = await database.GetPeopleListLongOperationAsync();
PeopleList.Add(result.First());
}
}
正如你看到的,我正在做與LoadData方法,它從數據庫中獲取數據的異步調用並將其添加到的ObservableCollection,這將更新數據網格(從綁定數據網格)
數據庫類,其中「模擬」的數據抓取:
public class Database
{
public IEnumerable<Person> GetPeopleListLongOperation()
{
// forcing "long" data load
Thread.Sleep(5000);
yield return new Person() { FirstName = "Name", LastName = "LastName", Age = new Random().Next(18, 40) };
}
public Task<IEnumerable<Person>> GetPeopleListLongOperationAsync()
{
return Task.Run<IEnumerable<Person>>(() =>
{
return GetPeopleListLongOperation();
});
}
}
我使用Task.Run獲取在後臺線程數據。問題是 - 它在Main Thread中運行,並且阻塞了UI。
有什麼建議嗎?我不知道了,如果我理解正確的異步操作...
編輯
自IEnumerable更改任務結果類型列出使其正常工作。有人可以解釋我爲什麼嗎?
public Task<List<Person>> GetPeopleListLongOperationAsync()
{
return Task.Run<List<Person>>(() =>
{
return GetPeopleListLongOperation().ToList();
});
}
謝謝。我知道關於IEnumerable集合的延遲加載,但我不知道它是這樣工作的。 – asiesom