在windows phone的sdk中,一个xaml页面的头两行行一般如下:
1: <phone:ApplicationPage
2: x:Class="XXX"
这里,XXX是你的类的名称,而它的基类是phone:ApplicationPage。
到目前为止,一切正常,不是么?
但是,当XXX的基类不是phone:ApplicationPage而是YYY时,你就会在cs文件中碰上CS0263错误:部分类的基类必须一致。
cs文件里对应的错误部分:
1: class XXX : YYY//error CS0263 here
显而易见,这是因为xaml离的第一行的问题,于是你试着把xaml的第一行换成
1: <local:YYY //local is a namespace prefix you defined
可是你又在xaml文件里碰上了"the name xxx does not exist in namespace yyy"这个问题.
"也许我需要rebuild?" 你想, 可是, rebuild之后,问题依旧,于是你没辙了.
怎么办?
其实这是vs的一个编译的次序问题.
xaml的编译过程中,对名字的搜索来自于已编译的cs文件,而xaml又是先于cs被编译的.于是你就得到了一个逻辑上的死锁:
要编译xaml文件,需要先成功编译YYY.cs,而此时YYY.cs尚未成功编译.
怎么办?很简单,分两步来就是了。
第一步,添加YYY.cs文件,确保其编译通过.
第二步,修改XXX.xaml和XXX.xaml.cs中的继承关系,改成继承自YYY。
于是编译成功了.
1 Overview
本文内容是个人在iOS上的异步编程的一些初步的心得体会,不保证完全正确,如有问题,欢迎指教。
2 运行模型
异步编程从来是与硬件和系统紧密相关的, 不同的硬件架构和不同的系统架构有不同的异步模型, 自然也会带来不同的异步编程方式。 要深究iOS上的异步编程, 首先就要了解iOS的异步模型。
2.1 事件驱动
“事件驱动”是iOS的异步模型中一个很重要的概念,也是iOS程序运行的概念。
所谓“事件驱动”本质上与Windows的“消息驱动”是相同的。 一个iOS程序至少有一个事件队列, 主程序干的唯一一件事情就是不断从这个事件队列中取出各种事件, 并调用对应的事件处理函数。 这 与windows程序的处理方式——消息驱动本质上是一模一样的。
2.2 Runloop
Runloop是iOS中的一个重要的概念, 在异步编程中常常要和它打交道。 而实质上, Runloop等价于 win32中的WinProc函数。 或者说, 它们干了一样的事情——从消息/事件队列中取出消息, 根据消息/ 事件的类型调用对应的回调函数。 所不同的是, win32下, 消息处理对用户是开放的——用户可以自 定义消息类型, 并向消息队列中插入这些消息并进行相应的处理。 而在iOS下, 事件完全被隐藏在在 runloop之中。 用户只知道有runloop的存在, 而runloop中的具体细节, 用户是无法接触的。
2.3 Delegate
既然用户无法接触事件的具体细节, 那么用户又怎么和runloop互动,利用iOS的事件驱动机制呢? Apple对此的回答是:delegate! Cocoa Touch中提供的各种UI控件, 几乎都有一个delegate成员, 同 时有一个对应的protocol:UIxxxDelegate。 这样,Apple就把事件隐藏了起来。 当runloop从事件队列 中取到事件时, 它会寻找到对应的控件实例, 然后调用对应的delegate成员的对应的处理函数, 也 就是客户提供的各种delegate中的函数。 当然,注册事件的回调函数并不仅仅有delegate这个死板的 方式。 对UIControl, 小气的Apple还是犹抱琵琶半遮面地提供了一些和Win32类似的Tag的——UICon- trolEvents。 这就是另一种注册事件回调函数的方式:[UIControl addTarget:action:forEvent:]。 当 然,回调的过程还是差不多的——runloop取事件, 取对象,调用相应的回调处理函数。
2.4 Single Thread!
iOS并不喜欢程序员使用多线程, Apple自己也很讨厌多线程, 于是iOS的很多机制都是单线程的, 这就包括runloop, 还有autorelease pool等等。 可是这些都是非常基础的机制。 所以,编程中应该 尽可能地使用单线程。
2.5 小结
iOS的运行模型可以归结为: 以单线程的事件驱动模型。 系统将用户的各种操作和系统的各种IO归 结各种事件, 放入统一的事件队列中, 由runloop统一处理。 用户可以通过各种delegate或者actions 或者notification等指定事件的处理方式, 但不能直接接触事件。 更不能自定义事件。 这种事件驱动 机制以单线程为基础。 也以单线程为边界。 系统只会为主线程自动添加事件队列, 而其他线程则需要 手动添加。 其他线程中的消息是不会自动被添加到主线程中的消息队列的, 除非手动指定。 所以才会 有那么多perform:inMainThreadXXX之类的work-around。 实际上就是往Main Thread里的事件队列里面 加事件而已。 这种单线程的消息驱动实际上是一种很古老的运行模型。 早期没有线程概念的时候,几 乎所有的GUI程序都是这么干的。 最多一个叫event,一个叫message而已。
3 异步编程
3.1 基本的概念
从上面的运行模型可以得到一些关于iOS上的异步编程的基本的概念。 首先,与PC上的异步编程的概 念不同, iOS上的异步更多的指的是操作时序上的不确定,而非并发操作。 也因此,在大部分情况下是 不需要担心并发操作带来的各种资源冲突和死锁问题的。 其次, iOS程序中, 几乎每一行代码都是由 各种事件引发的, 又是单线程, 因此会引发runloop的阻塞。 因此每个函数的执行时间应该尽可能的 短, 以便系统继续runloop。 第三, 在单次的事件处理中, 是不需要担心资源冲突的问题的, 因为 这时没有第二个线程会来访问这些资源——除非你非要用多线程。 但是, 在多次的事件处理中, 却必 须考虑资源冲突的问题。
3.2 事件种类
iOS的事件种类大约有以下几种:
1. 用户操作,比如各种手势、触摸、按键等等
2. Timer,专门的timer事件,用于各种定时器。从这里也可以看出,iOS的timer是“伪”timer,只 要runloop被阻塞了,那么timer永远不会被引发。
3. I/O事件,比如各种文件的读写和网络的读写等,异步IO是一个很节约CPU资源的东西,iOS采用异 步IO也在情理之中。
3.3 常见的资源冲突
事实上iOS上绝大部分的资源冲突来自于事件顺序的不确定。 比如异步的网络读取和用户操作对同一 个资源的操作导致的操作顺序的不确定。
而由于iOS是事件驱动的,除非在函数中使用了runloop,否则不需要担心资源在函数之外被改写。
基于wxpython 2.8,
svn download:
svn checkout http://noweb-file-editor-chinese.googlecode.com/svn/trunk/ noweb-file-editor-chinese-read-only
源码是nw文件。win32下的使用方式:notangle -Raction literal_editor.nw>action.bat&action.bat
会生成nweditor.py这个脚本.
在linux下使用notangle时,-L[格式]将在输出中插入line directive,比如-L'#line %L %N'就表示line directive的格式为#line [line number in nw file]\n。
但在windows下却不能这么输入,这是因为windows的console非常愚蠢,只会以空格键来区分参数。因此,-L'#line %L %N'这个在linux下分为两个参数的格式,却因为里面的空格键被windows识别为-L'#line、%L、%N'三个参数!
因此需要一些力气来避免这个问题:比如用特殊字符来代替空格,然后再用sed把这些特殊字符替换为空格:
notangle -R* -L#line!@#%L!@#%N|sed "s/!@#/ /g"
1.到http://www.ctan.org/tex-archive/web/noweb/binaries 下载noweb的dos版,解压到c:\noweb
2.下载windows的notangle.bat到c:\noweb\bin
3.下载nw_win32.zip,解压缩到c:\noweb\bin
4.安装minGW
5.安装msys到c:\msys
6.在msys下输入mingw-get install msys-awk
7.在msys下输入mingw-get install msys-sed
8.在msys下输入mingw-get install msys-libiconv
10.将c:\msys\bin和c:\noweb\bin加入PATH环境变量
11.安装active perl
说明:以上的c:\noweb和c:\msys都是可变的,只要保证两个bin目录都在PATH即可。
类似Funtional的用法:
void test(char*[] arg) { } test((char*[]){"a","b",0});