1.Windows Message related
What is the difference between a window message and a call back function?
When should one use a user defined window message and when should one use a call back function?
2. Thread related
What is multi-thread environment?
How to achieve data integrity in multi-thread environment and why it is important to do so?
What is a deadlock? 
3. GUI related
What does it mean by thread-safe GUI and how to make a GUI component thread-safe?每题100分,我会另开贴,明天晚上之前.

解决方案 »

  1.   

    软件模块之间总是存在着一定的接口,从调用方式上,可以把他们分为三类:同步调用、回调和异步调用。同步调用是一种阻塞式调用,调用方要等待对方执行完毕才返回, 它是一种单向调用;回调是一种双向调用模式,也就是说,被调用方在接口被调用时也会调用对方的接口;异步调用是一种类似消息或事件的机制,不过它的调用方向刚好相反,接口的服务在收到某种讯息或发生某种事件时,会主动通知客户方(即调用客户方的接口)。回调和异步调用的关系非常紧密,通常我们使用回调来实现异步消息的注册,通过异步调用来实现消息的通知。同步调用是三者当中最简单的,而回调又常常是异步调用的基础,因此,下面我们着重讨论回调机制在不同软件架构中的实现。  对于不同类型的语言(如结构化语言和对象语言)、平台(Win32、JDK)或构架(CORBA、DCOM、WebService),客户和服务的交互除了同步方式以外,都需要具备一定的异步通知机制,让服务方(或接口提供方)在某些情况下能够主动通知客户,而回调是实现异步的一个最简捷的途径。  对于一般的结构化语言,可以通过回调函数来实现回调。回调函数也是一个函数或过程,不过它是一个由调用方自己实现,供被调用方使用的特殊函数。  在面向对象的语言中,回调则是通过接口或抽象类来实现的,我们把实现这种接口的类成为回调类,回调类的对象成为回调对象。对于象C++或Object Pascal这些兼容了过程特性的对象语言,不仅提供了回调对象、回调方法等特性,也能兼容过程语言的回调函数机制。  Windows平台的消息机制也可以看作是回调的一种应用,我们通过系统提供的接口注册消息处理函数(即回调函数),从而实现接收、处理消息的目的。由于Windows平台的API是用C语言来构建的,我们可以认为它也是回调函数的一个特例。  对于分布式组件代理体系CORBA,异步处理有多种方式,如回调、事件服务、通知服务等。事件服务和通知服务是CORBA用来处理异步消息的标准服务,他们主要负责消息的处理、派发、维护等工作。对一些简单的异步处理过程,我们可以通过回调机制来实现。
      

  2.   

    1,part 1:消息方式的速度没有回调快。part 2:回调是系统来调用的,在c/c++中用CALLBACK指定回调函数。这样系统在某个事件时会调用这个回调函数。比如窗口处理过程,当有一个消息的目的是某个窗口时,系统会调用这个处理过程函数。part 3:回调函数起到了异步的作用,因为由系统内部来运作和实现,所以提高了系统的效率(一些比较频繁的操作一般被设计成回调函数)和安全。而且提高了系统的扩展性,便于操作系统根据系统的发展状况来优化算法。
    2,多线程环境运行在一个虚拟的分时系统上(time-sharing system),操作系统通过将cpu分成一个个的处理时间片,分发给不同的线程(具体的分发算法,有系统实现,对用户是保密的),每个线程在时间片结束的时候,必须保证他的当前状态被保存。一般的实现是在,在线程内部设计一个线程上下文,存储线程让出cpu时的寄存器状态,当线程再次获得cpu时,从这个线程上下文中将值加载到寄存器中,继续执行。这样保证了每个线程在用户看来是连续执行的。
    他的优点是提高了系统的负载能力,特别是在多cpu 的机器上。通过多线程可以更高效的使用cpu资源。这样的缺点也有,每次切换线程时(线程加载和让出),会浪费cpu ,并且因为系统是开放的,线程的数目并没有受到严格限制,所以这种切换耗费对系统来说有时是可观的,特别是线程有异常的时候,会强制获得额外的cpu时间。还有就是线程的同步问题。因为系统并不保证每个线程的绝对执行顺序(实际上也没有合适和有效的算法来支持这个模型),所以线程有可能死锁,饥饿,竞争等等。
    所谓deadlock,就是线程A拥有资源1,同时想拥有资源2;线程B拥有资源2,同时想拥有资源1。而两个线程在没得到想要的资源之前不能进行任何动作。这就是deadlock的典型情况。
    3,这个问题,mfc在设计的时候也没有作好。处于效率的考虑,我这么认为(因为MFC出生的年月是个c以及其他开发环境拼杀的时候),所以mfc的效率和简洁将是争夺市场的必须手段。
    实际上,mfc并不保证gui对象在mutithread env下的安全性。为了在多线程下能有效的运作,他的做法我的理解是这样的(不对的地方欢迎指出),在线程之间传递句柄,而不是对象或是指针(因为这没有安全保障),接收线程根据句柄,在线程的局部存储区(tls)建立句柄和对象的映射关系(就象当初c runtime lib迁移到mutithread env的时候的做法相似,将c全局变量记录在一个线程私有的tiddata结构中),每个线程都有自己的tls,这样一个句柄实际上对应了不同的对象。在线程执行的时候,就会使用正确的gui对象来执行了.
    接收线程是怎样根据句柄创建对象的呢?有两种方式,FromHandle函数,创建一个临时的对象,这个对象在onidle的时候会被强制删除,因此这个对象的引用在安全上不是永久的。这样做主要处于效率的考虑,因为gui对象都很吃内存,所以没有必要每个线程都永久存在。第二种方式,Attach函数,将一个建立好的对象和句柄attach,这样建立的对象是永久的,直到该对象被detach并被撤消.msdn警告说,在没有detach之前删除对象不是一种正确的方式,一般都会引起问题的。这也是句柄一个优点。
    所以,设计一个gui threaded safe程序,应该尽量传递句柄。但是并不是所有传递的句柄都象上面所说的那样能正确运行。比如,传递视图view的句柄,系统并不知道初始化这个句柄和保证在接受线程内的新产生的视图对象和该线程的doc-view template framwork的关系。所以会出现问题。具体的注意问题可以参看msdn文档。好累,也不知道自己的理解对不对,欢迎指出错误。
      

  3.   

    1、
    消息的组成:
    一个消息由一个消息名称(UINT),和两个参数(WPARAM,LPARAM)。当用户进行了输入或是窗口的状态发生改变时系统都会发送消息到某一个窗口。例如当菜单转中之后会有WM_COMMAND消息发送,WPARAM的高字中(HIWORD(wParam))是命令的ID号,对菜单来讲就是菜单ID。当然用户也可以定义自己的消息名称,也可以利用自定义消息来发送通知和传送数据。 谁将收到消息:
    一个消息必须由一个窗口接收。在窗口的过程(WNDPROC)中可以对消息进行分析,对自己感兴趣的消息进行处理。例如你希望对菜单选择进行处理那么你可以定义对WM_COMMAND进行处理的代码,如果希望在窗口中进行图形输出就必须对WM_PAINT进行处理。 未处理的消息到那里去了:
    M$为窗口编写了默认的窗口过程,这个窗口过程将负责处理那些你不处理消息。正因为有了这个默认窗口过程我们才可以利用Windows的窗口进行开发而不必过多关注窗口各种消息的处理。例如窗口在被拖动时会有很多消息发送,而我们都可以不予理睬让系统自己去处理。 窗口句柄:
    说到消息就不能不说窗口句柄,系统通过窗口句柄来在整个系统中唯一标识一个窗口,发送一个消息时必须指定一个窗口句柄表明该消息由那个窗口接收。而每个窗口都会有自己的窗口过程,所以用户的输入就会被正确的处理。例如有两个窗口共用一个窗口过程代码,你在窗口一上按下鼠标时消息就会通过窗口一的句柄被发送到窗口一而不是窗口二。 下面有一段伪代码演示如何在窗口过程中处理消息 LONG yourWndProc(HWND hWnd,UINT uMessageType,WPARAM wP,LPARAM) 

     switch(uMessageType) 
     {//使用SWITCH语句将各种消息分开 
      case(WM_PAINT): 
       doYourWindow(...);//在窗口需要重新绘制时进行输出 
       break; 
      case(WM_LBUTTONDOWN): 
       doYourWork(...);//在鼠标左键被按下时进行处理 
       break; 
      default: 
       callDefaultWndProc(...);//对于其它情况就让系统自己处理 
       break; 
     } 
    }  
      接下来谈谈什么是消息机制:系统将会维护一个或多个消息队列,所有产生的消息都回被放入或是插入队列中。系统会在队列中取出每一条消息,根据消息的接收句柄而将该消息发送给拥有该窗口的程序的消息循环。每一个运行的程序都有自己的消息循环,在循环中得到属于自己的消息并根据接收窗口的句柄调用相应的窗口过程。而在没有消息时消息循环就将控制权交给系统所以Windows可以同时进行多个任务。下面的伪代码演示了消息循环的用法: while(1) 

    id=getMessage(...); 
    if(id == quit) 
    break; 
    translateMessage(...); 
    }    当该程序没有消息通知时getMessage就不会返回,也就不会占用系统的CPU时间。 图示消息投递模式 
      在16位的系统中系统中只有一个消息队列,所以系统必须等待当前任务处理消息后才可以发送下一消息到相应程序,如果一个程序陷如死循环或是耗时操作时系统就会得不到控制权。这种多任务系统也就称为协同式的多任务系统。Windows3.X就是这种系统。 
      而32位的系统中每一运行的程序都会有一个消息队列,所以系统可以在多个消息队列中转换而不必等待当前程序完成消息处理就可以得到控制权。这种多任务系统就称为抢先式的多任务系统。Windows95/NT就是这种系统。 
    Windows平台的消息机制也可以看作是回调的一种应用,我们通过系统提供的接口注册消息处理函数(即回调函数),从而实现接收、处理消息的目的。由于Windows平台的API是用C语言来构建的,我们可以认为它也是回调函数的一个特例。2、
    多线程概念请参考:
    http://www.microsoft.com/china/msdn/techvoice/09.asp在多线程应用程序中最重要的就是访问共享资源时的同步问题,windows操作系统中可供选择的同步对象有很多比如CRITICAL_SECTION(临界区),Event(事件),Mutex(互斥体)等等死锁:
    由于资源占用是互斥的,当某个进程提出申请资源后,使得有关进程在无外力协助下,永远分配不到必需的资源而无法继续运行,这就产生了一种特殊现象死锁。 3、这一点enoloo(行者无疆) 说的差不多了,没有什么补充了!
    希望这些能对你有所帮助吧!