我实现了一个刷新按钮,该按钮读取数据库并检查是否有新条目并将其添加到ObservableCollection
中。我有一个刷新图标,刷新图标取决于IsRefreshing
的值。像这样:
new Thread(() =>
{
Thread.CurrentThread.IsBackground = true;
IsRefreshing = true;
//Reads database
//ObservableCollection.Add(NewValues)
IsRefreshing = false;
}).Start();
但是运行此命令会给我一个例外:
这种CollectionView不支持从与Dispatcher线程不同的线程对其SourceCollection进行更改。
我显然会以错误的方式进行操作,但是不确定执行后台任务时如何使UI保持响应状态?
答案 0 :(得分:2)
您不能从后台线程修改UI。所有受支持的.NET版本都允许使用async/await
在后台执行某些操作并返回到UI线程。
ADO.NET,实体框架,Dapper和大多数ORM支持异步执行。例如,ADO.NET的ExecuteReader
具有等效的ExecuteReaderAsync
方法。 EF的ToList()
有一个ToListAsync()
。 Dapper的Query
有QueryAsync
您应该将事件处理程序更改为以下内容:
private async void btn1_Click(object sender, RoutedEventArgs e)
{
using(var connection = new SqlConnection(_cnString)
{
IsRefreshing = true;
await connection.OpenAsync();
var results=await connection.QueryAsync<Value>(query);
//We're now back in the UI thread
_theCollection.AddRange(results);
IsRefreshing = false;
}
}
调用OpenAsync
或QueryAsync
时,.NET将在后台运行查询并释放当前(UI)线程。查询完成后,await
确保将在原始线程(即UI线程)上恢复执行。
答案 1 :(得分:0)
基本上,您必须将此项目添加到集合中,但必须在Dispatcher线程上执行此操作,
Application.Current.Dispatcher.Invoke(() => ObservableCollection.Add(NewValues));