又到了每年闲下来,嚷嚷着要开坑新项目的季节了。然而仔细一想,去年挖坑说是要填的CHIP8还没有动手呢。

你怎么回事,小老弟.jpg

然而不得不承认的是,打开Visual Studio,创建好一个名为CHIP8的项目,可以说是人类历史上的一大壮举了。俗话说的好,良好的开端是成功的一半嘛。(大雾)

经历了今年整个冬春COVID的闭门不出,一个夏天的人心惶惶,一个秋天的摸爬滚打,让人感慨万千。又到了冬天,而一切又总算是回到了正轨。好在功夫不负有心人,过去几年的努力没有白费,未来几年总算不愁没饭吃了。

回到正题,Qt的部署方式和常规的应用开发是有区别的。普通应用的开发,只要把依赖库按照编译时的需求配置好,环境变量配置好,就可以带着到处跑。

但是Qt不行,如果按照传统思维的缺啥补啥的思路的话,Qt反而会报错,提示类似Qt安装损坏的信息。

后来到网上搜索后发现,Qt是有一套平台部署工具的(https://doc.qt.io/qt-5/windows-deployment.html),按照里面的说明,执行`windeployqt.exe`,即可自动完成应用部署。部署完成后,目标目录下会出现一大堆依赖文件,跟随应用一起打包即可

让Visual Studio在每次编译完成后自动部署Qt应用的方法是,右键项目->生成事件->生成后事件,在此可以利用Visual Studio的内置变量辅助完成自动部署指令的编写。可以理解为,在这里执行的命令行是通过cmd.exe执行的,因而需要使用CMD语法。

Release配置文件下的命令可以写成如下形式:

"$(QMake_QT_HOST_BINS_)/windeployqt.exe" --release "$(TargetPath)"

需要注意一下的是,如果不使用--dir选项指定为文件夹形式(让windeployqt.exe自行搜索Qt可执行文件)的话,$(TargetPath)位置需要填写项目的Qt可执行文件位置。

之前因为要用到某些IPv6的网站,就把网线从不支持IPv6的路由器上拔下来,直接插到光猫上,拨号上网。

结果问题就来了。最近在收集3A大作,每次挂上bt大约一个小时左右,系统就会直接卡死。没错,不是自动重启,也没有蓝屏,整块屏幕就保持卡死前最后一刻的状态,硬盘灯也不闪。这导致,上百G的文件好不容易花上快半个小时校验完,还没下个多少,又得重新校验。这个问题连着出了四五次,使我提高了对这个问题的重视程度。

后来左思右想,想不出哪里出了问题,打算做出硬件出现了暗伤的结论。偶然想到唯一做出的硬件变更就是换了网络连接方式,打算死马当活马医,把网线插回路由器试试(这样电脑就没了IPv6,同时也不需要自己拨号了)。

结果。。

很快啊,啪的一下就好了,bt连着用了近10小时都没出再出现这个问题。

于是得出结论:Windows 8 + P8B75-V + bt + 拨号 = 大概率卡死。

至于为什么是这样,我也不知道

===============================
后记

尝试了一下,如果把下载速度限制在一个合适的范围,好像就不会翻车,用60M的宽带,限制在5000K下载就没问题。

http://mscrmtechie.blogspot.com/2015/08/visio-open-group-and-close-group.html

在用Visio画图的时候,使用了一些内置的组合控件,双击编辑内容的时候会自动打开新的窗口(还会自动把组件放大到窗口尺寸)。编辑的时候挺爽,但是编辑完以后,发现无法退出该模式,只能在右下角切换回原本的视图(也就意味着实际上这个窗口并没有关闭)。

自己在Visio里摸了一大圈,只发现了怎么打开这窗口,没发现怎么关。重点是,有时候关闭vsdx文件,之后再重新打开的时候,跳出来的是这个子窗口,而不是正常的全文件视图,每次都要多点几下好麻烦。网上冲浪后得知,有一个非常隐蔽的组合键Ctrl + F4可以关闭当前选中的子窗口。

跟隔壁的优秀大学生(暂定)聊天后才后知后觉地发现,原来げんしん是拿Unity写的。

然而某次启动的时候,不知道怎么把Unity内置的画质设置窗口碰出来了。

后来很好奇这窗口是怎么弄出来的,就去查了一下,没有找到什么快捷键,但是发现了一个参数,可以在启动的时候主动调出那个窗口:

<game>.exe -show-screen-selector

但是在游戏里试了一下,发现并不能生效,应该是游戏启动后有主动加载用户设置的逻辑。

import asyncio, time

async def a(s):
    import time
    await asyncio.sleep(1)
    print(s)

async def b():
    asyncio.ensure_future(a('asd'))
    asyncio.ensure_future(a('qwe'))
    await asyncio.sleep(2)
    print('b')

loop = asyncio.get_event_loop()
B = b()
loop.run_until_complete(B)

要注意的有几个地方:

  1. async def的函数在哪里都可以调用,但是在调用的时候,必须显式等待其结束,否则会出现RuntimeWarning: coroutine 'xxx' was never awaited。在async函数中调用async函数的话,可以使用await关键字直接阻塞等待;在非async函数中则必须设置事件循环器event looper,然后通过事件循环器对所有的异步async函数进行阻塞式等待,避免主线程在子线程完成前退出;
  2. 在协程中休眠线程不能用time.sleep(),而应该用asyncio.sleep(),否则休眠的是整个进程而不是目标协程;
  3. asyncio.ensure_future()比较有意思,提供了类似“用完就扔”的协程运行模式,不必在后续显式await该协程。