在.NET 4.5中,新的异步机制非常好用,但是有一点很容易搞错,那就是一旦一个await 完成了,或者说是你的一个异步任务完成了,那么接下去由谁(哪个线程上下文)来直接执行之后的代码?在Wpf中(或在Metro中),当你进行await操作后,或者使用task.GetAwaiter()返回的TaskAwaiter 对象的OnCompleted(将你想要的后续操作放入它中),那么你会发现,它们都是在UI线程中执行的(使用Thread.CurrentThread.ManagedThreadId查看,但是Metro没有Thread,但这个比照WPF就行)。代码如下:
private async void clicked(object sender, RoutedEventArgs e)
{
id0= Thread.CurrentThread.ManagedThreadId;
await Go();
}
async Task Go()
{
var task = GetAnswerToLife();
text.Text = text.Text +await task;
}
async Task<int> GetAnswerToLife()
{
var task = Task.Delay(5000);
var aw = task.GetAwaiter();
aw.OnCompleted(() =>
{
var id1 = Thread.CurrentThread.ManagedThreadId;
});
await task;
int answer = 21 * 2;
var id2=Thread.CurrentThread.ManagedThreadId;
// text.Text = text.Text +answer + "+"+id;
return answer;
}
其中clicked是一个Button的Click事件,那么我们断点每个id处,会发现id0=id1=id2。
若是在控制台应用程序中,那么结果就很不一样了,我这里就不帖代码了,把以上这段代码移到控制台应用程序上很容易。你会发现,id0和id1,id2不一样,也就是id0是主线程的id,其他的id是其他线程的id,那么即使我在每个task上加上这段代码:
task.ConfigureAwait(true);
也还是没用(注意:若ConfigureAwait为true,在UI应用中,往往让调用该task的线程回来执行task完成后的代码,往往就是UI线程,若为false,则会让执行task具体任务的工作线程来执行。所以,当你把task.ConfigureAwait(false);添加到wpf的项目里时,你会发现,id0就不等于id1和id2了)。
那具体的原因是什么呢?突然发现,要完成以上的这种可以让一个线程有空时回到await处的前提条件是,该线程应该是一个基于消息循环的应用程序,这个是由编译器来将剩余代码打包成一个消息到消息队列中,所以普通的控制台应用程序没有这种机制,也就不可能让主线程回到它去过的地方执行了。参考如下的机制:
while (!thisApplication.Ended)
{
wait for something to appear in message queue
Got something: what kind of message is it?
Keyboard/mouse message -> fire an event handler
User BeginInvoke/Invoke message -> execute delegate
}
分享到:
相关推荐
在本文中,我们将深入探讨如何使用C#和WPF(Windows Presentation Foundation)技术来构建一个功能丰富的应用程序屏幕,该屏幕能够实现应用的列表展示、搜索和启动安装。WPF是.NET框架的一部分,它提供了一个强大的...
在WPF(Windows Presentation Foundation)应用程序中,与Web API进行交互是常见的需求,尤其是在需要从服务器获取数据或发送用户操作到后端时。本教程将深入探讨如何利用HttpClient类在WPF应用中异步调用Web API,...
在本文中,我们将深入探讨如何使用C#和WPF(Windows Presentation Foundation)来调用Windows 8 Metro应用程序,这是现代Windows应用开发的一个重要方面。在Windows 8及更高版本的操作系统中,Microsoft引入了Metro ...
在本文中,我们将深入探讨如何在C#的WPF(Windows Presentation Foundation)应用程序中引用Mahapps.Metro库,并利用HTTP通信进行数据的发送与接收。Mahapps.Metro是一个流行的UI框架,它为WPF提供了现代化的、类似...
在C#编程中,`await`关键字和`Task.WhenAll()`是处理并行任务的关键工具,它们能够帮助开发者实现高效且优雅的异步编程。本文将深入探讨这两个概念以及`Task.Delay()`的原理。 首先,`await`关键字是C#异步编程的...
Example for binding an ObservableCollection to a ListView and using async await Task to update the data
8. **并行编程支持**:通过Task Parallel Library (TPL)和async/await关键字,开发者可以更方便地编写并发和异步代码,提高应用程序的响应速度。 9. **Windows 8集成**:虽然该书是在Windows 8发布之前编写的,但它...
在Windows Presentation Foundation (WPF) 中,开发人员经常需要集成对Microsoft Office文档的支持,以便用户可以直接在应用程序中查看PPT(PowerPoint)、Word和Excel文件。这个任务涉及到使用特定的库或者API来...
ESRI Silverlight API 和 Runtime SDK for WPF 是Esri公司为开发地理信息系统(GIS)应用程序提供的两个关键组件。这两个框架都是用于构建丰富的、交互式的地图应用程序,尤其在Web客户端环境中。在本文中,我们将...
标题中的“在GUI界面上运行Console程序”意味着我们要探讨如何将传统的控制台应用程序(Console Application)集成到图形用户界面(GUI)中,以便用户可以在友好的图形环境下与之交互。这种做法常见于需要提供可视化...
在VS中,创建一个新的WPF应用程序项目,然后定义一个ViewModel类,其中包含一个ObservableCollection对象,用于存储ListView的数据项。这些数据项可以包含一个表示进度的属性,如`ProgressValue`。 ```csharp ...
在“WPF 文件更新小程序”中,可能使用了`BackgroundWorker`、`Task`或`async/await`关键字来启动后台任务。这些方法可以将文件更新操作放到单独的线程上执行,同时保持UI的响应性。当后台任务完成时,更新UI的状态...
在C#和WPF(Windows Presentation Foundation)的环境中构建UDP通信是常见的任务,尤其是在开发实时性和性能要求较高的应用时。本教程将详细讲解如何在WPF界面中实现一个高效的UDP通信系统,确保程序运行时界面无假...
通过以上步骤,你可以在WPF的ItemsControl中实现异步加载,提高应用程序的性能和用户体验。当然,具体实现可能会根据项目需求和现有框架有所不同,但这些基本概念和方法应该能为你提供一个良好的起点。记得在实践中...
9. **多线程和并发**:在.NET 4.5中,探讨异步编程模型(async/await)在WPF中的应用,以提高应用程序的响应性。 10. **部署和测试**:介绍如何发布和部署WPF应用,以及进行测试的最佳实践。 这本书的源码部分通常...
**WPF程序放大器**,通常指的是用于增强Windows Presentation Foundation(WPF)应用程序性能和功能的工具或技术。WPF是Microsoft开发的一种用于构建桌面应用的框架,它提供了丰富的用户界面设计、图形渲染和数据...
在WPF应用中,这种文件通常包含数据库连接信息、用户界面布局参数或其他应用程序特定的设置。开发者可能会使用XML格式来存储这些配置,因为XML易于解析,且结构清晰。 综合上述内容,这个WPF示例项目旨在教你如何...
在Windows Presentation Foundation(WPF)开发中,为应用程序创建一个“正在加载”提示功能图标是一项常见的需求,特别是在处理大量数据或执行长时间操作时,这样的提示能够提供更好的用户体验,让用户了解程序的...