随着拥有多个硬线程CPU(超线程、双核)的普及,多线程和异步操作等并发程序设计方法也受到了更多的关注和讨论。本文主要是想与园中各位高手一同探讨一下如何使用并发来最大化程序的性能。
多线程和异步操作的异同
多线程和异步操作两者都可以达到避免调用线程阻塞的目的,从而提高软件的可响应性。甚至有些时候我们就认为多线程和异步操作是等同的概念。但是,多线程和异步操作还是有一些区别的。而这些区别造成了使用多线程和异步操作的时机的区别。
异步操作的本质
所有的程序最终都会由计算机硬件来执行,所以为了更好的理解异步操作的本质,我们有必要了解一下它的硬件基础。 熟悉电脑硬件的朋友肯定对DMA这个词不陌生,硬盘、光驱的技术规格中都有明确DMA的模式指标,其实网卡、声卡、显卡也是有DMA功能的。DMA就是直接内存访问的意思,也就是说,拥有DMA功能的硬件在和内存进行数据交换的时候可以不消耗CPU资源。只要CPU在发起数据传输时发送一个指令,硬件就开始自己和内存交换数据,在传输完成之后硬件会触发一个中断来通知操作完成。这些无须消耗CPU时间的I/O操作正是异步操作的硬件基础。所以即使在DOS这样的单进程(而且无线程概念)系统中也同样可以发起异步的DMA操作。
线程的本质
线程不是一个计算机硬件的功能,而是操作系统提供的一种逻辑功能,线程本质上是进程中一段并发运行的代码,所以线程需要操作系统投入CPU资源来运行和调度。
异步操作的优缺点
因为异步操作无须额外的线程负担,并且使用回调的方式进行处理,在设计良好的情况下,处理函数可以不必使用共享变量(即使无法完全不用,最起码可以减少共享变量的数量),减少了死锁的可能。当然异步操作也并非完美无暇。编写异步操作的复杂程度较高,程序主要使用回调方式进行处理,与普通人的思维方式有些初入,而且难以调试。
多线程的优缺点
多线程的优点很明显,线程中的处理程序依然是顺序执行,符合普通人的思维习惯,所以编程简单。但是多线程的缺点也同样明显,线程的使用(滥用)会给系统带来上下文切换的额外负担。并且线程间的共享变量可能造成死锁的出现。
适用范围
在了解了线程与异步操作各自的优缺点之后,我们可以来探讨一下线程和异步的合理用途。我认为:当需要执行I/O操作时,使用异步操作比使用线程+同步I/O操作更合适。I/O操作不仅包括了直接的文件、网络的读写,还包括数据库操作、Web Service、HttpRequest以及.Net Remoting等跨进程的调用。
而线程的适用范围则是那种需要长时间CPU运算的场合,例如耗时较长的图形处理和算法执行。但是往往由于使用线程编程的简单和符合习惯,所以很多朋友往往会使用线程来执行耗时较长的I/O操作。这样在只有少数几个并发操作的时候还无伤大雅,如果需要处理大量的并发操作时就不合适了。
VS 2015 启动调试时报“无法启动 IIS Express Web 服务器”,或 IIS Express 启动了,但网页无法打开,除了百度告诉你的方法,可以试试:
网站项目 右键属性 - “Web”选项卡 - 点击“项目 URL”右侧的“创建虚拟目录”
本文是一个初学者对苹果开发证书的理解,有一定局限性,不适合所有苹果开发者参考,欢迎批评指正。
发布 iOS 应用主要有三块内容:Certificates, Identifiers & Profiles
Certificates(证书):是用来给应用程序签名的
Identifiers(标识符):一个应用对应一个 ID,相当于应用程序的身份证
Provisioning Profiles(描述文件):它将证书、标识符、设备结合起来,形成一个描述文件,让 Xcode 知道需要打一个怎么样的 .ipa 包
如何创建证书
创建 App ID 就不详说了,不要使用带通配符的名称。值得一提的是,如果要使用推送,必须勾选“Push Notifications”,其它功能按需勾选。
创建证书,需要用到 Mac 电脑上的“钥匙串访问”来生成一个“本地证书”(CSR 文件):
打开“钥匙串访问” - 证书助理 - 从证书颁发机构请求证书 - 保存到磁盘
然后就可以拿这个本地证书去 Apple Developer 里生成“开发证书”或“发布证书”(CER 文件)。打包证书和推送证书生成过程类似,区别是选择“App Store and Ad Hoc”还是“Apple Push Notification service SSL”。下载后添加到钥匙串就完成了。
添加测试设备就不提了。
然后就是描述文件,同样有开发和发布两种。开发主要是用于 Xcode 环境中;发布中还分两种:App Store 是用于正式上线的,Ad Hoc 是用于测试设备的。下一步选择 App ID,下一步选择证书,然后给 Profile 取个能够分辨的名字,生成的是一个 mobileprovision 文件。
提供证书文件给第三方打包平台
一般需要提供“iOS Distribution 证书”、“推送证书”、“Ad Hoc”和“App Store”类型的 Profiles、App ID 以及 iTunes Connect 中的 Apple ID(不是指登录的邮箱,是指在 iTunes Connect 中创建的 App 在商店中的 ID)。
证书其实跟 App ID 不是一一对应的关系,多个 App 是可以使用同一个证书的。可以单独创建,到期互不影响。Download 后是 .cer 格式,用“钥匙串”工具可以导出 .p12 证书并设置密码。
如果由于命名无序或创建错误导致无法分辨上架中的 App 用的是哪个证书,哪个描述文件,那么,首先要知道这个 App ID 是多少(就是 iTunes Connect 中所谓的“套装 ID”),然后在 Provisioning Profiles 中挨个查看对应的 App ID,点击“Edit”还能看到使用的证书。
有些平台需要 .pem 文件,是由 .p12 文件通过一个命令转化而来的,具体可以百度。
证书过期怎么办
创建一个呗,然后描述文件 Edit,选择新的证书。
推送证书过期怎么办
在 App ID 里 Edit 就能查看 Push Notifications 项的 SSL Certificate 是否过期。如果过期需要重新创建证书,可以直接在 App ID 的 Edit 里快捷创建(需要“钥匙串”配合)。
不用重新提交 App Store 审核
换一台电脑,证书要怎么导过去
这个问题适用于自己使用 Xcode 开发应用的情况,暂时问一下百度吧。
注:本文部分总结来自百度,未经证实。
Apple Push Services 和 APNs Production iOS 这两种类型有什么区别?
升级“微信登录 1.1.6”插件后,发现微社区发帖提示“抱歉,您的请求来路不正确或表单验证串不符,无法提交”,查看更新日记发现微社区域名更换为 wsq.discuz.com,导致表单验证不通过的原因就是它了。
解决方法是打开:\source\class\helper\helper_form.php
找到:'
http://wsq.discuz.qq.com', 24
或:'
http://wsq.discuz.qq.com/', 25
替换为:'http://wsq.discuz.com/', 22
然后清空目录:\data\cache\qrcode\
至于帖子分享给朋友或朋友圈的标题和图片不正常的问题,目前还没有办法解决,听说是该插件要收费的节奏,具体可以参与官方讨论:
http://www.discuz.net/forum-2-1.html
另外,如果发现微社区里的用户头像或表情不能正常显示,一般是由于做了防盗链引起的,只要在白名单里加上 *.discuz.com 就行了
编者按:本文作者 Nick Babich 在文中介绍了几种 “提高” 加载速度的方法。
当我们设计产品的时候,我们没有办法模拟不同的加载速度。因此如果用户等待太长的时间才能看到内容,并不是我们特意的安排。
网速不稳定,尤其是当我们加载图片或音乐时,时间会较长。在这种情况下,我们不得不考虑在这种间隙向用户展示什么内容才能让他们感觉不枯燥。
加载动图(Spinner)效果不佳
加载 Spinner 并不是暗示加载或思考的正确方式。默认加载图标(例如 iOS 的加载动画效果是从中心点辐射的灰色线条)通常具有消极的含义。它们应用于多种操作系统功能之中,包括设备启动、连接到网络或者加载数据。

人们讨厌只看到加载 Spinner,但是却看不多进度或时间。让用户盯着一个下载进度条或者旋转圈会让跳出率提高。
不确定的等待时间比已知的、有限的等待时间让人觉得更长。你应该给你的用户一个清晰地等待时间。

进度条可以告诉用户这个过程需要花费多长时间,但是一般不太正确。你可以通过一些方法隐藏过程中的延迟,例如你可以在开始的时候让速度显示地快一点,在结尾的时候,显示速度慢一点。进度条不应该中断,否则用户就会认为这个 App 卡住了。
后台操作
在后台操作中包含行为有两个优点——用户可见;在用户真正发出请求时就会加载完毕。当程序在后台运营时,给用户呈现一些其他的内容。一个很好的案例是在 Instagram 中加载图片。用户一旦选择想要分享的图片,就开始加载。

在后台加载图片的过程中,Instagram 邀请用户添加标题和标签,当用户准备按 “分享” 键时,加载过程就完成了,这时候就可以立刻分享图片了。
仿真内容和 Placeholder(占位符)
如果你无法缩短加载时间,那么你应该试图让用户在等待中更高兴一点。可以利用这个时间显示一些临时的信息。为了提高用户的参与度,可以使用仿真内容作为文本和图片。
几点小建议:
1、加载屏幕不应该太亮。不需要太吸引眼球。Facebook 的灰色 Placeholder 就是一个很好的例子。当加载内容时使用模板元素,让用户熟悉将要加载的内容的整体结构。

2、如果要加载图片,你可以在 placeholder 中使用加载图片的主色调。Medium 的图片加载效果比较好。首先加载一个小型的模糊图片,然后转化成一个清晰的大图片。

使用 placeholder 和仿真内容并没有加快加载过程,但是在用户眼中加载速度好像变快了。
分散用户的注意力
为了不让用户在等待时感到枯燥,可以适当分散他们的注意力。你可以使用一些有趣的、始料未及的东西吸引用户的注意力,为 App 加载赢得充足的时间。

动画片可以分散访客的注意力,让他们忽略加载时间。
结论
用户讨厌等待,如果你让用户觉得他们没有等待,那么他们就会喜欢你的 App。一定要让用户觉得 App 的加载时间比他预计的短。
在 ASP.NET Core 或 ASP.NET 5 中部署百度编辑器请跳转此文。
本文记录百度编辑器 ASP.NET 版的部署过程,对其它语言版本也有一定的参考价值。
【2020.02.21 重新整理】
下载
从 GitHub 下载最新发布版本:https://github.com/fex-team/ueditor/releases
按编码分有 gbk 和 utf8 两种版本,按服务端编程语言分有 asp、jsp、net、php 四种版本,按需下载。
目录介绍
以 v1.4.3.3 utf8-net 为例,

客户端部署
本例将上述所有目录和文件拷贝到网站目录 /libs/ueditor/ 下。
当然也可以引用 CDN 静态资源,但会遇到诸多跨域问题,不建议。
在内容编辑页面引入:
<script src="/libs/ueditor/ueditor.config.js"></script>
<script src="/libs/ueditor/ueditor.all.min.js"></script>在内容显示页面引入:
<script src="/libs/ueditor/ueditor.parse.min.js"></script>如需修改编辑器资源文件根路径,参 ueditor.config.js 文件内顶部文件。(一般不需要单独设置)
如果使用 CDN,那么在初始化 UE 实例的时候应配置 serverUrl 值(即 controller.ashx 所在路径)。
客户端配置
初始化 UE 实例:
var ue = UE.getEditor('tb_content', {
// serverUrl: '/libs/ueditor/net/controller.ashx', // 指定服务端接收文件路径
initialFrameWidth: '100%'
});其它参数见官方文档,或 ueditor.config.js 文件。
服务端部署
net 目录是 ASP.NET 版的服务端程序,用来实现接收上传的文件等功能。
本例中在网站中的位置是 /libs/ueditor/net/。如果改动了位置,那么在初始化 UE 的时候也应该配置 serverUrl 值。
这是一个完整的 VS 项目,可以单独部署为一个网站。其中:
net/config.json 服务端配置文件
net/controller.ashx 文件上传入口
net/App_Code/CrawlerHandler.cs 远程抓图动作
net/App_Code/ListFileManager.cs 文件管理动作
net/App_Code/UploadHandler.cs 上传动作
该目录不需要转换为应用程序。
服务端配置
根据 config.json 中 *PathFormat 的默认配置,一般地,上传的图片会保存在 controller.ashx 文件所在目录(即本例中的 /libs/ueditor/)的 upload 目录中:
/libs/ueditor/upload/image/
原因是 UploadHandler.cs 中 Server.MapPath 的参数是由 *PathFormat 决定的。
以修改 config.json 中的 imagePathFormat 为例:
原值:"imagePathFormat": "upload/image/{yyyy}{mm}{dd}/{time}{rand:6}"
改为:"imagePathFormat": "/upload/ueditor/{yyyy}{mm}{dd}/{time}{rand:6}"
以“/”开始的路径在 Server.MapPath 时会定位到网站根目录。
此处不能以“~/”开始,因为最终在客户端显示的图片路径是 imageUrlPrefix + imagePathFormat,若其中包含符号“~”就无法正确显示。
在该配置文件中查找所有 PathFormat,按相同的规则修改。
说到客户端的图片路径,我们只要将
原值:"imageUrlPrefix": "/ueditor/net/"
改为:"imageUrlPrefix": ""
即可返回客户端正确的 URL。
当然也要同步修改 scrawlUrlPrefix、snapscreenUrlPrefix、catcherUrlPrefix、videoUrlPrefix、fileUrlPrefix。
特殊情况,在复制包含图片的网页内容的操作中,若图片地址带“?”等符号,会出现无法保存到磁盘的情况,需要修改以下代码:
打开 CrawlerHandler.cs 文件,找到
ServerUrl = PathFormatter.Format(Path.GetFileName(this.SourceUrl), Config.GetString("catcherPathFormat"));替换成:
ServerUrl = PathFormatter.Format(Path.GetFileName(SourceUrl.Contains("?") ? SourceUrl.Substring(0, SourceUrl.IndexOf("?")) : SourceUrl), Config.GetString("catcherPathFormat"));如果你将图片保存到第三方图库,那么 imageUrlPrefix 值设为相应的域名即可,如:
改为:"imageUrlPrefix": "//cdn.***.com"
然后在 UploadHandler.cs 文件(用于文件上传)中找到
File.WriteAllBytes(localPath, uploadFileBytes);在其下方插入上传到第三方图库的代码,以阿里云 OSS 为例:
// 上传到 OSS
client.PutObject(bucketName, savePath.Substring(1), localPath);在 CrawlerHandler.cs 文件(无程抓图上传)中找到
File.WriteAllBytes(savePath, bytes);在其下方插入上传到第三方图库的代码,以阿里云 OSS 为例:
// 上传到 OSS
client.PutObject(bucketName, ServerUrl.Substring(1), savePath);最后有还有两个以 UrlPrefix 结尾的参数名 imageManagerUrlPrefix 和 fileManagerUrlPrefix 分别是用来列出上传目录中的图片和文件的,
对应的操作是在编辑器上的“多图上传”功能的“在线管理”,和“附件”功能的“在线附件”。
最终列出的图片路径是由 imageManagerUrlPrefix + imageManagerListPath + 图片 URL 组成的,那么:
"imageManagerListPath": "/upload/ueditor/image",
"imageManagerUrlPrefix": "",
以及:
"fileManagerListPath": "/upload/ueditor/file",
"fileManagerUrlPrefix": "",
即可。
如果是上传到第三方图库的,且图库上的文件与本地副本是一致的,那么将 imageManagerUrlPrefix 和 fileManagerUrlPrefix 设置为图库域名,
服务端仍然以 imageManagerListPath 指定的路径来查找本地文件(非图库),但客户端显示图库的文件 URL。
因此,如果文件仅存放在图库上,本地没有副本的情况就无法使用该功能了。
综上,所有的 *UrlPrefix 应该设为一致。
另外记得配置不希望被远程抓图的域名,参数 catcherLocalDomain。
服务端授权
现在来判断一下只有登录用户才允许上传。
首先打开服务端的统一入口文件 controller.ashx,
继承类“IHttpHandler”改为“IHttpHandler, System.Web.SessionState.IRequiresSessionState”,即同时继承两个类,以便可使用 Session,
找到“switch”,其上插入:
if (用户未登录) { throw new System.Exception("请登录后再试"); }即用户已登录或 action 为获取 config 才进入 switch。然后,
else
{
action = new NotAllowedHandler(context);
}这里的 NotAllowedHandler 是参照 NotSupportedHandler 创建的,提示语 state 可以是“登录后才能进行此操作。”
上传目录权限设置
上传目录(即本例中的 /upload/ueditor/ 目录)应设置允许写入和禁止执行。
基本用法
设置内容:
ue.setContent("Hello world.");获取内容:
var a = ue.getContent();更多用法见官方文档:http://fex.baidu.com/ueditor/#api-common
其它事宜
配置上传附件的文件格式
找到文件:config.json,更改“上传文件配置”的 fileAllowFiles 项,
同时在 Web 服务器上允许这些格式的文件可访问权限。以 IIS 为例,在“MIME 类型”模块中添加扩展名。
遇到从客户端(......)中检测到有潜在危险的 Request.Form 值。请参考此文
另外,对于不支持上传 .webp 类型的图片的问题,可以作以下修改:
config.json 中搜索“".bmp"”,替换为“".bmp", ".webp"”
IIS 中选中对应网站或直接选中服务器名,打开“MIME 类型”,添加,文件扩展名为“.webp”,MIME 类型为“image/webp”
最后,为了在内容展示页面看到跟编辑器中相同的效果,请参照官方文档引用 uParse
若有插入代码,再引用:
<link href="/lib/ueditor/utf8-net/third-party/SyntaxHighlighter/shCoreDefault.css" rel="stylesheet" />
<script src="/lib/ueditor/utf8-net/third-party/SyntaxHighlighter/shCore.js"></script>
其它插件雷同。
若对编辑器的尺寸有要求,在初始化时设置即可:
var ue = UE.getEditor('tb_content', {
initialFrameWidth: '100%',
initialFrameHeight: 320
});
今天终于把大量占用论坛服务器带宽的元凶找到了!
我们的论坛使用阿里云的 ECS+RDS+OSS+CDN 架构,最近发现 ECS 的带宽怎么都不够用了,也没有什么突发事件呀,再说附件都在 OSS 上。观察了云监控控制台,发现半夜里的流量也不减呀,白天更是触顶下不来,坛友们真是不辞辛劳为 PV 作贡献啊。
我对 CentOS 还是不够熟悉的,查阅了一些资料后,终于找到方向入手了。
重点肯定是日志文件了,但是面对每天几个 G 的大块头,还真是无法下手,一条一条看估计胡子都白花花了。
那么,首先安装 GoAccess 这个好东西(yum install goaccess)
然后进入网站日志目录,用 GoAccess 来分析一下(goaccess -f xxxxxx.log -a),具体用法参官网
选择日志格式,nginx 默认为 NCSA Combined Log Format,空格选中,回车确认
稍等片刻就可以看到主界面了,统计信息丰富多彩,统计结果一目了然,看截图,如果你分析的日志文件是当前正在使用中的,它还会每秒刷新主界面,让你看到实时统计
大致分为几块内容:
按 1 定位到“按天访问量”
按 2 定位到“最多次被请求的 URL”
按 3 定位到“最多次被请求的静态文件”
按 4 定位到“最多次被请求的 404”
按 5 定位到“最多次请求的用户 IP”
按 6 定位到“用户的操作系统”
按 7 定位到“用户的浏览器”
按 8 定位到“按小时的统计”
按以上数字键后,再按回车可以查看具体或更多的信息,按 s 可以更换排序,按 q 返回或退出
那么我先找 5 最多次请求的用户 IP,排前面的全部是从 60.191.127.4 到 60.191.127.26 的 IP,每个 IP 都是几 G 级的带宽占用。
负责任的,你必须保证这些 IP 不是政府或大企业的对公 IP,而且得拿这些 IP 直接去日志文件里搜到底请求了哪些 URL。经查证,它们只请求版块的帖子列表页,没有请求任何图片、脚本、样式等,还有,UserAgent 中没有带 Spider 之类的关键字,证明不是搜索引擎的蜘蛛,那么就可以果断认为它“不是人”
啥都不说了,找到 nginx 的 conf 配置文件,在 server 中添加 deny 60.191.127.0/24;
检查配置:nginx -t
使配置生效:nginx -s reload
呵呵,马上就能在阿里云监控里看到过山车式的折线了。
另外,备注下查看各IP的连接数的命令:
netstat -an|grep :80| awk '{print $5}'| cut -d':' -f1| sort |uniq -c
使用 DTS 在迁移 SQL Server 数据库时,若源数据库的版本是 2012,则迁移到 RDS (版本 2008 R2)警告版本不兼容,但是可以正常迁移;若源数据库的版本是 2014,则出现错误,无法迁移。
如果数据量较小,则可以这样操作:
在源数据库上右键 - 任务 - 生成脚本 - 编写整个数据库及所有数据库对象的脚本
接下来应该不用介绍了。
如果数据量较大,用上面的方法就力不从心了,可以:
在源数据库上右键 - 任务 - 导出数据 - 选择数据源(SQL Server Native Client),填写 RDS 的连接信息,下一步
这种方法的缺点是只导数据,会丢失主键、外键、索引等信息,需要重新设置。
当然也可以用 Navicat 的数据传输工具,可以完整地迁移整个数据库,但如果中途出现 Err (毕竟是第三方)则传输会中断,只能重来一遍并取消勾选出问题的那个表,全部完成后再用 SSMS 来单独导那个表,手动添加主键、外键、索引等。
- 如何识别 MacBook Pro 机型
- 如何识别 Mac mini 机型
- 查看保修服务和支持范围
也可以查到出厂时间、机器配置等
- Boot Camp:Microsoft Windows 操作系统的系统要求
查看什么设备使用什么版本的 Boot Camp 来安装什么版本的 Windows。
在“受支持的 Windows 版本”中注意这行字“Windows 8:Windows 8 或 8.1、Windows 8 或 8.1 Pro(仅 Boot Camp 5)”,但是我装专业版还是有问题(安装显卡驱动蓝屏),实践经果是跟专业版还是企业版无关。
Boot Camp 的版本必须根据设备和 Windows 版本来定(查表),否则无法安装。
本教程使用 U 盘 OS X 启动盘和 U 盘 Windows 安装盘,硬盘安装稍有不同。
系统安装前
准备工作
各系统下所有资料备份到移动硬盘或网盘
制作系统盘
如果 OS X 系统已经无法进入,则只能用 Internet Recovery 重装了(联网下载 5G 左右的安装包)。否则可以进入 OS X,从 App Store 下载最新的 OS X 安装包制作 USB 启动盘。
制作 USB OS X 启动盘教程:适用于 Mavericks(10.9) 及更旧版本、适用于 Yosemite(10.10) 及更新版本
使用 OS X 的 Boot Camp 助手制作 U 盘 Windows 安装盘(若使用一般的 Windows 安装盘,安装完成后会遇到无法安装 Boot Camp 的问题,即使是正确的版本)
安装 OS X
版本
本文适用且不限于 OS X 10.8.4 - 10.9.3
分区与安装
插入 USB OS X 启动盘,开机,出现白屏即按住 option / Alt 键,选择相应的启动盘(联网恢复方式:开机按“option”+“command”+“R”,在磁盘工具分区时如果遇到“未能卸载磁盘”,就可以用联网恢复的方式重新分区)
进入磁盘工具,分区:3 个分区:(安装 OS X 的分区必须放在最后)
选中第 3 个分区:Macintosh HD,Mac OS 扩展(日志式),100G,选项:GUID 分区表,用于安装 OS X
选中第 2 个分区:BOOTCAMP,MS-DOS(FAT),100G,用于安装 Windows
选中第 1 个分区:DATA,ExFAT,用于存放数据(公共盘)
应用,退出磁盘工具,选择重新安装 OS X,选择安装在 Macintosh HD 分区
等待约 30 分钟安装完成
Finder 中推出并拔除 USB OS X 启动盘
安装 Windows
安装
插入 USB Windows 安装盘
在 OS X 中进入:系统偏好设置 - 启动磁盘 - 选择 USB Windows 启动盘 或者 重新启动系统 - 响完“当”且白屏前按住 Option 或 Alt 键,选择 USB 图标的 Windows 项(不是 EFI Boot 那项)
全新安装,选中 BOOTCAMP 分区并格式化,安装。(注:[待测]下次尝试删除全部分区并重新分区,如果能安装并启动成功,就是没有 OS X 的 Windows 单系统了。由于制作 U 盘 OS X 启动盘和 Windows 安装盘都需要在 OS X 环境下进行,所以必须权衡是否真的只需要单系统,否则下次只能用 Internet Recovery 方式重装了)
安装完成后,安装 Boot Camp 支持软件(已集成到 Windows 安装盘内)
必须通过右下角的 Boot Camp 来重启进入 OS X,否则在移除 USB Windows 安装盘的情况下无法进入各系统。(此条为真?待测)
正常弹出并拔除 USB Windows 安装盘
其它
Apple Wireless Keyboard
确保设备管理器的蓝牙设备中有 Apple 字样的驱动名称(即蓝牙驱动是通过 Boot Camp 安装的)
打开键盘电源
右击 Windows 任务栏小图标中的蓝牙图标,添加新设备
配对