时间:9:21 2010-10-11
环境:
开发环境:VS2008 +XAML2CPP.EXE + SWE 2 + BLEND 2
运行环境:WINCE 6.0 R3
硬件加速: DirectX
动机
发现:在Silverlight for windows embedded 当中控件状态的改变,同时集中于同一个线程当中,效果不满意,因为其只是显示最后一个状态的界面,没有中间过程。
背景:
在开发当中遇到下列情况:用户删除文件过程的提示,用户复制文件过程的提示。
此过程由几个阶段所构成的,初始状态,执行状态,已完成状态。且每一个阶段其均是要求的提示图标。
用户控件
为了方便地完成任务,我们制件了一个用户控件。且定义其三种状态:初始状态,执行状态,已完成状态。
图1 提示用户的控件
图2 用户控件的三种状态
图3 用户控件处于初始状态
图4 用户控件处于等待状态的效果图
图5 用户控件处于已完成状态
使用此控件
我们将此控件作为子控件嵌入到主窗口当中(如图6 所示),且在C++源代码当中命名为:uctlDeleteTipsDlg.
图6 用户控件在主窗口当中作为子控件使用
图7 主窗口的界面
删除文件的实现
图8 实现代码
事件过程与效果
用户操作流程
用户在用户控件上单击“是”按钮,系统会显示等待图标且执行业务逻辑代码。当业务逻辑代码执行完之后,显示已经完成图标。
实际效果
当用户单击“是”按钮之后,系统没有显示等待图标,而是处于假死机状态( 界面不响不更新也不响应用户的事件)
直到业务逻辑完成之后,才显示已完成图标。
对于这种效果是不满足的。
暂时想到的解决方案
我在主窗口当中添加了三个按钮,分别用来执行三种状态,结果是可以的。
此结果的原因是因为不同时,且不在同一个线程当中。如果只是不在同个方法当中,其结果第一次的结果是一样的。
我的想法:将业务逻辑作为一个线程来完成。当线程完成之后通知主程序。主程序来完成显示已完成图标。
线程
silverlight for windows embedded 其没有完成对于线程的封装。所以只能自己来完成了。
我对于线程封装的要求:其应该类似于C#当中的异常通信,用户只要创建一个线程,且可以向这个线程注册一个线程完成事件监听器,因为当线程完成之后其能够通知主程序。且不要有WIN32 API的影子,以面向对象的方式来使用,这一点与C#也类似。
首先GOOGLE,codeproject, pudn,baidu. 但没有找到让我满意的结果,没有办法,只能自己来搞了。
图9 线程类
图10 线程工厂类( 代理类还更为亲切些)
#pragma once #include <xamlruntime.h> typedef enum ThreadStatus { RUN = 1, PAUSE = 2, STOP =3 }; class thread { public: HANDLE handleThread; // 线程的句柄 DWORD dwThreadId; // 线程的标识符 BOOL bThreadExit; ThreadStatus status; bool isAlive; // 是否创建 thread(LPVOID pfn, LPVOID param ) { Init( pfn, param); } ~thread(void) { } void Init( LPVOID &pfn, LPVOID ¶m){ // CreateThread // handleThread = CreateThread( NULL, NULL, // (LPTHREAD_START_ROUTINE)pfn, // param, // NULL, // &dwThreadId); handleThread = CreateThread( NULL, NULL, (LPTHREAD_START_ROUTINE)pfn, param, CREATE_SUSPENDED, &dwThreadId); if( handleThread != NULL ){ isAlive = true; }else{ isAlive = false; } } public: HRESULT Start(){ if( !isAlive ){ return S_FALSE; } // 运行线程 ::ResumeThread( this->handleThread); return S_OK; } protected: }; class threadFactory{ public: thread * pthread; IXRDelegate<XREventArgs>* pThreadCompletedDelegate; threadFactory( LPVOID pfn, LPVOID param ){ pthread = new thread( pfn,param); this->pThreadCompletedDelegate = NULL; } ~threadFactory(){ /* delete pthread; */ } void Start(){ this->pthread->Start(); if( this->pThreadCompletedDelegate != NULL ){ thread temp(WaitThread,this); // 等待业务线程结束,以通知用户的线程 temp.Start(); } } void Notify(){ // __try{ this->pThreadCompletedDelegate->Invoke(NULL,NULL); }__except(EXCEPTION_EXECUTE_HANDLER){ RETAILMSG( TRUE, (L"Exception \n")); } } template <class T, typename ArgType> HRESULT AddThreadCompletedListen(T* pT, HRESULT (T::*pfn)(IXRDependencyObject*, ArgType*)){ this->pThreadCompletedDelegate = CreateDelegate(pT,pfn); this->pThreadCompletedDelegate->Release(); return S_OK; } static void WaitThread( LPVOID param){ threadFactory * factory = (threadFactory*)param; ::WaitForSingleObject(factory->pthread->handleThread,INFINITE); factory->Notify(); delete factory; // 相当于自杀 } };
怎么样使用此线程
业务逻辑的代理
线程结束通知的代码
HRESULT Tips(IXRDependencyObject* source,XREventArgs* args){
if(FAILED(this->uctlDeleteTipsDlg->GoToVisualState(L"DoneStatus",false)))
{
return S_FALSE;
}
RETAILMSG( TRUE,(L"Message: THREAD has dead -------------------- \n"));
return S_OK;
}
使用线程的效果
图11 准备开始
图12 正在执行业务逻辑
图13 已经完成
使用注意事项
1. 注意去设置XRWindowCreateParams::AllowsMultipleThreadAccess 为true, 但我发现两个现象:
A.不管设不设置其都是可以运行的。
B. 其运行都次之后,会产生数据访问异常。
2.关于线程类的使用
小结
此思路相当的不完善,希望大家能提出想法