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.

使用.net core 2.0的坑

找个地方下载VS Installer,它会自动提示更新.
使用.net core 2.0的坑 - yww325 - 程序员
真是个坑!SDK的安装选项里如果有一个勾是选择VS2017 support就好了,需要客户去自己寻找自己的各个产品之间的依赖关系,或者只是在release notes里提一下,这是多么失败的产品经理的输出。安装界面上给个Visual Studio Integration选项很难做吗?

2. 新的.NetStandard类型的Library才是未来,它可以同时被桌面App和CoreApp使用。特别是如果用了.NetStandard2.0的LIbrary,因为nuget restore的时候可以有兼容模式,这种Library就可以引用一些没有满足.NetStandard的老的NugetPackage.

建立Library项目是不要选.NetCore下面的项目,因为它们只能用这些Framework,

使用.net core 2.0的坑 - yww325 - 程序员
结果就是这种dll不能被桌面项目直接使用。
1>C:\Program Files\dotnet\sdk\2.0.0\Sdks\Microsoft.NET.Sdk\build\Microsoft.NET.Sdk.Common.targets(87,5): error : Project ‘\Testlibrary\Testlibrary.csproj’ targets ‘.NETCoreApp,Version=v2.0’. It cannot be referenced by a project that targets ‘.NETFramework,Version=v4.7’.

而如果选了.Net Standard项目,则可以用以下framework列表,这样它就可以被桌面项目使用了。

使用.net core 2.0的坑 - yww325 - 程序员

但是这个.Net Standard Library引用的其他NugetPackage不会自动被输出到桌面项目里,运行时会报错文件找不到。所以Library用到的NugetPackage还要自己手动加。 这里感觉应该有个选项开关类似于copy to local这样的才行啊。

(还有一个workaround,就是打包成本地nugetPackage被桌面项目引用,这样才会自动加依赖的package,但是这样搞得内部的框架也必须要用pakcage引用而不能直接项目引用,太不方便了)