Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/amazon-s3/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何在执行后台任务时保持UI的响应性_C#_Wpf - Fatal编程技术网

C# 如何在执行后台任务时保持UI的响应性

C# 如何在执行后台任务时保持UI的响应性,c#,wpf,C#,Wpf,我实现了一个刷新按钮,它读取数据库并检查任何新条目,并将它们添加到可观察集合中。我有一个刷新图标,它根据IsRefreshing的值旋转。像这样: new Thread(() => { Thread.CurrentThread.IsBackground = true; IsRefreshing = true; //Reads database //ObservableColle

我实现了一个刷新按钮,它读取数据库并检查任何新条目,并将它们添加到
可观察集合中。我有一个刷新图标,它根据
IsRefreshing
的值旋转。像这样:

new Thread(() =>
        {
            Thread.CurrentThread.IsBackground = true;
            IsRefreshing = true;

            //Reads database
            //ObservableCollection.Add(NewValues)

            IsRefreshing = false;
        }).Start();
但运行此命令会给我一个例外:

此类型的CollectionView不支持从不同于Dispatcher线程的线程更改其SourceCollection


显然,我的做法是错误的,但我不确定在执行后台任务时如何保持UI响应?

您不能从后台线程修改UI。所有受支持的.NET版本都允许使用
async/await
在后台执行某些操作并返回UI线程

NET、实体框架、Dapper和大多数ORM都支持异步执行。例如,ADO.NET的
ExecuteReader
有一个等价的
ExecuteReaderAsync
方法。EF的
ToList()
有一个
ToListAsync()
。Dapper的
Query
具有
querySync

您应该将事件处理程序更改为以下内容:

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;
    }
}
private async void btn1\u单击(对象发送方,路由目标)
{
使用(var connection=newsqlconnection(_cnString)
{
IsRefreshing=真;
等待连接。OpenAsync();
var results=await connection.QueryAsync(查询);
//我们现在回到UI线程中
_collection.AddRange(结果);
IsRefreshing=假;
}
}

调用
OpenAsync
QueryAsync
时,.NET将在后台运行查询并释放当前(UI)线程。当查询完成时,
wait
确保将在原始线程(即UI线程)上继续执行。

基本上,您必须将此项添加到集合中,但必须在Dispatcher线程上执行,如下所示:

Application.Current.Dispatcher.Invoke(() => ObservableCollection.Add(NewValues));

您不应该访问其他线程在主线程中创建的控件。不要使用原始线程、uase async/await和tasks。ADO.NET和EF已经支持异步执行。在任何情况下,您都不能从其他线程修改UI发布事件处理程序的代码和从数据库读取的代码。当前代码使用
线程
应被删除开始阅读此处:当
等待
可用时不需要。如果要发布来自另一个任务或线程的进度更新,请使用进度类。此外,
应用程序.Current.Dispatcher.Invoke中介绍了使用进度类。如果UI线程不可用,则可以使应用程序死锁busy@PanagiotisKanavos我不从他的部分可以看到很多代码,但你承担了全部。如果他试图添加到绑定到某个ListView或类似控件的可观察集合,那么他无法这样做,因为UI不能从UI以外的任何线程更新。因此,添加到可观察集合需要在UI线程上进行。这就是为什么你要调用Invo我不认为。在
wait
之后,您将返回UI线程。这意味着您可以修改任何元素。这就是为什么不需要使用Invoke。我建议您检查provided@PanagiotisKanavos我唯一看到的是他打开了一个完全不同的线程,并在这个线程中完成他的工作从这个线程调用一个UI元素,他必须在UI线程上调用它