async方法fn直接.result会堵塞无法结束的问题

 碰到过这个一个问题,fn是一个aysnc方法,在spotfire程序的UI线程上经过多层方法调用到的时候如果是直接写var a = fn().result就把spotfire卡死了。result也拿不出来(看不到结果a)

这实际是一个没有正确使用异步方法的问题。异步方法虽然可以同步调用(.result),但如果是UI线程里这么干,就出事了。async就要await调用,如果当前方法不是异步的(比如上层的接口定下来了,不过好像加不加async不影响接口实现),那就只能多包一层线程来同步调用。
下面第一篇文章解释了await关键字实际干了什么事(即SynchronizationContext.Current.post,post到UI线程的消息队列里),以及.result干了什么事情(同步执行)
下面这篇文章解释了SynchronizationContext在异步编程中的作用,特别是和ExecutionContext的差异(ExecutionContext是内部的,一般不用管)

所以使用await关键字调用async方法不会有问题。因为UI线程没有阻塞,UI的消息队列还有机会处理Post来的http异步请求结束的消息。

但是fn.result会阻塞,因为是同步执行,所以UI的onClick方法根本没有结束,UI消息队列没有空来执行其它东西的能力(http异步请求的东西取回来了却结束不了)。
所以Three ways out:
1.使用await调用aysnc, 这是最优方案,因为UI click事件执行完全不需要等待http请求,消息队列没有空转着等待。
2. ConfigureAwait(false),这个算是workaround,UI click事件还是等http请求结束了才全部结束,而且中间还要利用一个别的线程来执行http请求结束存放变量的操作,然后再回到UI线程来结束整个click.这个过程中消息队列在白白等待着。
3.上面的task.run( ()=>fn()).result方法再起一个线程来启动fn,在不能改Library,又不能用await的情况下也是一种写法。
之所以建议Library中总是ConfigureAwait(false)就是怕有用户在使用当前Task或上层Task(不一定是这个Task(Awaitable)的直接调用)时,用.Result的方式”同步地使用异步方法”,而没有使用await(不是所有的上层调用都像UI的button click方法private async void Button_Click()都支持async.
关于async和Task的使用可以参考:
实际上async方法基本都需要返回一个Task,上述的async void Button_Click()是一个不好的pattern,   “fire-and-forget”机制, caller没有办法了解这个方法执行完成的情况或者抛出的错误。只有在最上层的UI event等系统方法才这么写。
我觉得其实是微软的UI Event代码带坏了大家,完全可以设计成必须要返回一个Task的机制,哪怕是Task<void>,也能保证后面的代码被suspend到这个task之后。如果自己写的代码是aysnc void,则因为没有GetAwaiter()(属于Task),则不能被await,结果就直接跑过去了,即使aysnc void方法里有下一层的await调用,因为上层没有等它执行完,这个await调用也不会suspend aysnc void方法后的代码执行,仅仅是系统看到await再开一个线程去跑而已。顺序关系需要GetAwaiter()串起来才能实现。

修复windows 7系统无法自动更新的问题

下载下面的小程序运行就好。

Reset Windows Update Components. Short link

<<http://go.microsoft.com/?linkid=9665683>>

This tool automates the most common fixes to issu?s with the Windows Update site.

Note this Fix it 50202 Solution has two modes Default and Aggressive.

You should run the Fix it solution in Default mode and determine if it resolves your problem with Windows Update before running it inAggressive mode.

The Update History section at <<http://windowsupdate.microsoft.com>> will be blank/empty after running the Fix It in AGGRESSIVEmode.