模拟自主运行的对象(live object)

博客介绍了在C++中实现多线程类以产生自主运行对象的方法。以animate_object为例,阐述了构造函数、线程函数、析构函数的实现,解决了析构时的死锁问题,还提到多实例访问共享变量需互斥同步,可模拟复杂程序并在多CPU环境并行。

  C++提供了封装对象的方法,但是没有提供多线程的支持,如果需要产生多个同时自主运行的对象(live-object),就需要定义我们自己的多线程类。MSDN中的《Using Multithreading and C++ to Generate Live Objects》对这个有趣的技术进行了详细的介绍。

       废话少说,先来看一下产生一个支持多线程类的结构,下面以animate_object为例,先看一下animate_object的构造函数:

animated_object::animated_object(LPSTR lpImageName, short sType)
{
  < Initialize some member variables here. >
  hThread = CreateThread(NULL,
                         0,
                        (LPTHREAD_START_ROUTINE)ObjectThreadRoutine,
                         this,
                         0,
                        (LPDWORD)&this->dwIDThread);
  iStatus = (hThread != (HANDLE)NULL);
};

可以看到,在构造函数中产生了一个线程,hThread, 用于表示该对象所联系的对象,并且用iStatus表示是否成功产生了该线程,其中hThread作为private成员,其并不为外界所知,外部环境获得该对象的信息的唯一方式就是通过iStatus,这样实现了数据的封装,而且iStatus还可以用于表示所有初始化工作的成功或者失败

       下面是线程函数。由于线程函数不能够是非静态成员函数,所以需要使用一个全局函数

long WINAPI ObjectThreadRoutine(animated_object *fpObj)
{ 
 return (fpObj->MoveAndDraw());
} 

该全局函数实际上是一个stub function, 在函数内部调用了animated_object 对象的成员函数MoveAndDraw,为了让该全局函数可以使用animated_object的私有函数,需要将该全局函数声明为animated_object的友员函数。

       下面是析构函数

         animated_object::~animated_object(void)
{
  if (iStatus)
  {
   WaitForSingleObject(hThread,INFINITE);
   CloseHandle(hThread);
  };
  DeleteObject(hImage);
  MessageBeep(-1);
}; 

当对象析构的时候,在析构函数内部等待线程结束,然后关闭线程,注意只有当初始化成功(iStatus0)的时候,才会调用这些cleanup的工作,现在唯一的问题就是:如果该线程自己调用析构函数,就会产生死锁(A调用BB返回的条件是A已经结束),这里可以采用postMessage的方式,特别要注意的是如果使用sendMessage,仍然会产生死锁(可以用共享变量的方法避免死锁)关闭的方式,在线程函数中使用postMessage将关闭自己的消息发送给外部控制线程,由外部控制线程关闭线程,这样在调用析构函数的时候就不会产生死锁的问题了。

       同步问题:当产生多个该类的实例的时候,如果需要访问共享变量,需要使用互斥同步的方法,下面是animated_object的核心部分

long animated_object::MoveAndDraw(void)
{ int iTempX, iTempY;
  HDC hDC;
  while(!bFinished)
    {
      iTempX = iX+iXVelocity;
      iTempY = iY+iYVelocity;
 
/* The next four IF statements check whether a wall has been hit after a move.
   If yes, the position is reset to the wall, the direction reversed,
   and a random value added. */
 
< Wall-collison detection code follows here... */  
 
      EnterCriticalSection(&csSerializeDraw);
      hDC=GetDC(the_pond->hWndApplication);
 
< Erase the old image from the screen: >
 
      BitBlt(hDC,iX,iY,iImageWidth,iImageHeight,NULL,0,0,WHITENESS);
      iX = iTempX;
      iY = iTempY;
      iCalories-=MOVE_DEDUCTION;
 
/* Do three things here to determine whether one has died:  */
/* (a) Do additional per-move work, depending on the object type. */
/* (b) Determine whether we have enough fuel left to survive. */
/* (c) Ask the pond whether a collision has occurred. */
 
      if (!ObjectSpecificThreadRoutine(hDC) ||    // LOOK HERE!
          iCalories < 0 ||
          !the_pond->NewCoordinates(iHandle,iX,iY))
        bFinished=TRUE;
      else
/* Redraw the object. */
 
< Redraw code is in here.>
 
      ReleaseDC(the_pond->hWndApplication,hDC);
      LeaveCriticalSection(&csSerializeDraw);
/* Delay the object before moving on. */
      Sleep(DELAY);
    };   // end of while loop. Going past here means we are dead...
/* Inform the window that the thread has terminated, so it can clean up the object. */
 
  PostMessage(the_pond->hWndApplication,WM_OBJECT_DIED,(WPARAM)iHandle,NULL);
  return(TRUE);
};

       结论:通过使用C++的封装特性和多线程,可以很好的模拟live object,其他复杂的应用也可以通过这种方式进行扩展,可以模拟bolzman机这种需要同步运行的程序,并且作为并行程序在多CPU环境下“真正”的并行。

源码地址: https://pan.quark.cn/s/d1f41682e390 miyoubiAuto 米游社每日米游币自动化Python脚本(务必使用Python3) 8更新:更换cookie的获取地址 注意:禁止在B站、贴吧、或各大论坛大肆传播! 作者已退游,项目不维护了。 如果有能力的可以pr修复。 小引一波 推荐关注几个非常可爱有趣的女孩! 欢迎B站搜索: @嘉然今天吃什么 @向晚大魔王 @乃琳Queen @贝拉kira 第三方库 食用方法 下载源码 在Global.py中设置米游社Cookie 运行myb.py 本地第一次运行时会自动生产一个文件储存cookie,请勿删除 当前仅支持单个账号! 获取Cookie方法 浏览器无痕模式打开 http://user.mihoyo.com/ ,登录账号 按,打开,找到并点击 按刷新页面,按下图复制 Cookie: How to get mys cookie 当触发时,可尝试按关闭,然后再次刷新页面,最后复制 Cookie。 也可以使用另一种方法: 复制代码 浏览器无痕模式打开 http://user.mihoyo.com/ ,登录账号 按,打开,找到并点击 控制台粘贴代码并运行,获得类似的输出信息 部分即为所需复制的 Cookie,点击确定复制 部署方法--腾讯云函数版(推荐! ) 下载项目源码和压缩包 进入项目文件夹打开命令行执行以下命令 xxxxxxx为通过上面方式或取得米游社cookie 一定要用双引号包裹!! 例如: png 复制返回内容(包括括号) 例如: QQ截图20210505031552.png 登录腾讯云函数官网 选择函数服务-新建-自定义创建 函数名称随意-地区随意-运行环境Python3....
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值