各位大哥,小弟我最近要做一个模拟线程同步的程序,要求有图形界面,我设计了一下,大体试了一下,但是遇到很多问题,请各位百忙之中看一下,帮我出出主意,不胜感激!(基于单文档应用程序)
                                         一:总体的设想
     首先,对于公交车的线路,模拟的话,我是画了一个矩形;
     其次,对于站点的模拟,我画了几个实心的圆来代替;
     最后,公交车,我用一幅公交车位图来模拟;
                                         二:代码
     1:首先是公交线路和站点的模拟部分:
          在OnDraw函数中我这样做:
           CPen mypen, * oldpen;
mypen.CreatePen(PS_SOLID,10,RGB(0,0,200));
oldpen=(CPen *)pDC->SelectObject(&mypen);
       pDC->RoundRect(CRect(100,100,800,500),CPoint(50,50));
       pDC->SelectObject(oldpen);
CBrush brush(RGB(153,0,251));
  CBrush *oldbrush=pDC->SelectObject(&brush);
        pDC->Ellipse(CRect(435,85,465,115));
        pDC->Ellipse(CRect(85,285,115,315));
pDC->Ellipse(CRect(435,485,465,515));
        pDC->Ellipse(CRect(785,285,815,315));
        pDC->SetTextColor(RGB(255,50,0));
pDC->TextOut(400,470,CString("电子科大长安校区"));
        pDC->TextOut(130,270,CString("郭杜站"));
pDC->TextOut(420,130,CString("电子商城"));
pDC->TextOut(750,270,CString("电子科大老校区"));
      2:其次:我对于公交车的模拟:
          我加载了一幅位图:
          在OnInitialUpdate()函数中,我这样做:
              CView::OnInitialUpdate();
m_static.Create(NULL, WS_CHILD|WS_VISIBLE|SS_BITMAP, CRect(m_carpoint.x, m_carpoint.y, 32,         32), this); 
    m_static.SetBitmap(LoadBitmap(AfxGetInstanceHandle(), (LPCTSTR)IDB_BITMAP1));
GetParentFrame()->RecalcLayout();
SetTimer(2,1,NULL);
       3:线程控制部分:
           利用互斥量来实现,建立两个进程分别是公交车司机进程和售票员进程
           位图初始化的时候,是m_carpoint.x=450;m_carpoint.y=500;其中m_carpoint是车子的位置,在Ontimer中是这样写的:
          if(m_carpoint.x>100&&m_carpoint.y==500&&car_on)
{
m_carpoint.x-=1;
        m_static.MoveWindow(m_carpoint.x,500,30,30,true);
}
else if(m_carpoint.x==100&&m_carpoint.y>100&&car_on)
{
m_carpoint.y-=1;
        m_static.MoveWindow(100,m_carpoint.y,30,30,true);
}
else if(m_carpoint.x<800&&m_carpoint.y==100&&car_on)
{
m_carpoint.x+=1;
m_static.MoveWindow(m_carpoint.x,100,30,30,true);
}
else if(m_carpoint.x==800&&m_carpoint.y<500&&car_on)
{
m_carpoint.y+=1;
m_static.MoveWindow(800,m_carpoint.y,30,30,true);
}
if(m_carpoint.x==450&&m_carpoint.y==100||
m_carpoint.x==100&&m_carpoint.y==300||
m_carpoint.x==800&&m_carpoint.y==300||
m_carpoint.x==450&&m_carpoint.y==500)
{
car_on=false;
}
else
       car_on=true;
       我所理解的线程就是:司机在开车之前去判断售票员是否关门了,售票员开门之前看司机是否停车了,XP操作系统给每个线程分配 时间片,用完的话换到宪哥进程,一次实现程序的并发,在我这个例子中,车子是不是停车应该是在Timer中判断,是不是车子到达了指定的站点,司机线程停车,Sleep两秒中,互斥量交给售票员,售票员开门,释放互斥量,交给司机,司机得到door_on是false即车子关了,开车,等等
       DWORD WINAPI CZuoyeView::busdriver(LPVOID lpParameter)
{
while(true)
{
if(!door_on)
{
car_on=true;
WaitForSingleObject(hMutex,INFINITE);
    Sleep(2000);
}

else
{
//car_on=false;
ReleaseMutex(hMutex);
}

}
return 0;
}
DWORD WINAPI CZuoyeView::conduct(LPVOID lpParameter)
{
     while(true)
{
if(!car_on)
 {
door_on=true;
WaitForSingleObject(hMutex,INFINITE);
Sleep(2000);
 }
 else
 {
            door_on=false;
            ReleaseMutex(hMutex);
 }
}
return 0;
}
以上是我的线程函数,但是问题来了:首先,在司机线程判断的时候,也许时间片在售票员那里,该售票员判断的时候,也许时间片在司机那里,如果线程里面去判断是不是停车,那就更糟了,因为,是不是停车由一个点决定,是转瞬即逝的,时间片显得很长,会错过好多站点
,这个程序目前是异常状态,希望大家看一看,我也许对线程同步的概念理解的不是很到位,希望大家指导!也许这个程序设计的时候有什么问题?怎么解决车子停车对与m_carpoint的判断?希望你的回帖和意见,不胜感激,我发帖从来都是回帖有分,希望大家给点主意,分不够我再加!!
        

解决方案 »

  1.   

    你可以用一个临界区实现
    用APIR 几个函数EnterCriticalSection(&g_cs);
    LeaveCriticalSection(&g_cs);对其实加入就可以当然用信号量也是可以
    这个线程同步应该不难
      

  2.   

    我也是刚刚接触这些东西,问题都很简单····
    第一:在线程函数里面的While(true){}这句话不就是说,当这个线程得到时间片??还是这个线程占据互斥事件(我看到的例子中存在没有用互斥事件的,所以应该不是这种情况)?
    第二:sleep(2000)的意思是说,这个线程挂起,并且放弃对互斥时间的拥有权,那么这时候互斥事件被谁拥有了??将要发生什么发生,我觉得应该是谁在等待事件,就是哪个进程中有WaitForSingle(ObjecthMutex,INFINITE);,谁就是下一个拥有这个事件的吧!而我要实现的就是在每个站点等待2000毫秒,这个语句是达到这种效果的吗??
    第三:WaitForSingle(ObjecthMutex,INFINITE);中的INFINITE意思是,“满足条件”就可以得到对互斥事件的拥有权,对吧?那么“满足条件”是什么意思?我的理解是:当有互斥事件没有人占用的时候,这种说法对吗?是否准确?
    第四:我身边有人用信号量,所以我不想用信号量,我要用互斥事件,应该都是一样的吧!所以大家就考虑互斥事件吧!
    第五:我在Timer中每隔一毫秒判断一下当前车子的坐标,是否会出现判断失误?意思就是车子到达了站点,但是这个时刻并没有发送货收到timer的消息,造成没有停车的状况?我设计的是1毫秒车子移动单位“1”的距离,所以我认为,不会出现这种状况,大家认为呢?如果我用Ontimer函数中去判断是不是到站,从而决定car_on的true还是false(car_on是判断车子是不是在开动的bool变量),不符合我依靠线程去控制car_on的本质目的,所以不可以这么做
    第六:car_on是判断车子是不是在开动的bool变量,这个变量我如果不在Timer中设计,那在线程函数里面判断吗?我觉得那样的会更糟糕!因为,在线程里面用if语句判断的话,鬼知道在我需要判断的时候,是不是有判断语句的线程在执行啊??
    第七:我发现在CZuoyeView(大家肯定知道我工程的名字就叫zuoye了)中定义的类成员,在线程函数中竟然不可以访问,所以我一气之下都换成全局变量了?不知道这是什么原因?
    第八:在这个题目中,到底线程应该扮演什么角色?“司机在开车之前去判断售票员是否关门了,售票员开门之前看司机是否停车了”就是全部吗??具体应该都写些什么东西?
    请高手一一指点····
      

  3.   

    同上,时间片不是你要考虑的事情,多线程比较重要的一点是要找到符合实际情况的模型。稍微考虑了下,一个比较笨的办法是做三个event,分别为
    1,司机等待售票员关门,计时器开始走,2秒后停车,计时器关闭。
    2,售票员等待司机停车,开始售票。
    3,售票员等待售票完成,关门。用WaitForSingleObject也可以,道理是一样的。
      

  4.   

    1,while就是表示一直执行,与其他关系不大.
    2.sleep表示挂起,互斥事件原来是谁的还是谁的.......
    3.infinite表示无限等待....
    4.信号量可以有多个,互斥可以看为只有一个资源时的信号量.
    5.不会
    6.线程可以看为在同时执行(非实时).
    7想要访问CZuoyeView的成员,可以考虑传递CZuoyeView的指针,通过CZuoyeView指针来访问,不过不推荐
      

  5.   

    一,while true就是简单的死循环,要是跳出循环你的线程就over了。
    二,sleep 2000 就是执行到该语句的线程挂起2秒,在大约2000个毫秒以后会被重新排到被操作系统选择的线程中。放弃互斥事件??谁告诉你的?
    三,INFINITE字面意思是无限。。WaitForSingleObject就是说无限等待这个信号,你也可以设成等待多少毫秒之后继续执行不等待,具体用法忘了。。请参考msdn。
    四,多线程要选用符合实际情况的模型。。
    五,不会。
    六,会被两个线程访问到的变量,加临界区。
    七,类成员对象可以访问啊,要看你怎么访问。。贴出来看看。
    八,我上面说了。。
      

  6.   

    思路应该很清楚!用线程控制一些变量,车子(位图)根据这些变量去做响应变化,哪位高手花费点时间写出来啊!也好给我们研究研究啊!对了,还有个功能就是,在车子的状态发生变化的时候,比如说要开车了,就要有字符出现“开车了!”,售票员有”卖票“的信息提示,要用TextOut函数吗?在线程里面输出的时候,第一个参数我老是弄错,哪位高手写一下,供大家研究一下···期待中,不然,过两天我只有去问问老师了
      

  7.   

    晚上没事,写了个,贴出来供交流。。写的烂,高手莫笑图形界面我就不搞了,主要是两个线程的关系。
    用到两个信号,g_hBusDoorClosed和g_hBusStopped,用来使两个线程交互执行,其实用一个也可以做到,这里为了看到清楚一点,用来两个。
    还有一个临界区cs,是发现在cout的时候,线程的交换会导致输出流异常,LZ的图形界面可能也要考虑到这个。#include "stdafx.h"
    #include "windows.h"
    #include <iostream>using namespace std;CRITICAL_SECTION   cs; // Critical section for output, non-related about driver & conductorHANDLE g_hBusDoorClosed; // Global handle of the door's state. if singaled, the door is CLOSED.
    HANDLE g_hBusStopped; // Global handle of bus' state, if singaled, the bus is STOPPED.
    bool g_bFinish; // Global flag, when bus reach the last stop, make it true.
    DWORD WINAPI threadDriverProc( LPVOID lpParam )
    {
    unsigned short iBusStop = 0; // When bus stops, += 1, only for output. for (;iBusStop < 10;)
    {
    EnterCriticalSection(&cs);
    cout << "Bus now stops at " << iBusStop << endl;
    LeaveCriticalSection(&cs); WaitForSingleObject(g_hBusDoorClosed, INFINITE); // Wait until conductor close the door. EnterCriticalSection(&cs);
    cout << "Bus now leaves " << iBusStop << endl;
    LeaveCriticalSection(&cs); ++ iBusStop;
    Sleep(2000);
    SetEvent(g_hBusStopped); // Stop the bus.
    }
    g_bFinish = true;
    return 0;
    }DWORD WINAPI threadConductorProc( LPVOID lpParam )
    {
    for (;!g_bFinish;)
    {
    SetEvent(g_hBusDoorClosed); // Close the door.
    WaitForSingleObject(g_hBusStopped, INFINITE); // Wait until driver stop the bus. for (unsigned short i=0; i<3; i++)
    {
    EnterCriticalSection(&cs);
    cout << "Sell ticket to passenger " << i << endl;
    LeaveCriticalSection(&cs); Sleep(500);
    }
    }
    return 0;
    }int _tmain(int argc, _TCHAR* argv[])
    {
    HANDLE hDriver;
    HANDLE hConductor; InitializeCriticalSection(&cs);
    g_hBusDoorClosed = CreateEvent(NULL, false, false, L"g_hBusDoor");
    g_hBusStopped = CreateEvent(NULL, false, false, L"g_hBusStopped");
    g_bFinish = false; hDriver = CreateThread( 
                NULL,              // default security attributes
                0,                 // use default stack size  
                threadDriverProc,        // thread function 
                NULL,             // argument to thread function 
                0,                 // use default creation flags 
                NULL);   // returns the thread identifier  hConductor = CreateThread( 
                NULL,              // default security attributes
                0,                 // use default stack size  
                threadConductorProc,        // thread function 
                NULL,             // argument to thread function 
                0,                 // use default creation flags 
                NULL);   // returns the thread identifier  // Wait until both two threads exit.
    WaitForSingleObject(hDriver, INFINITE);
    WaitForSingleObject(hConductor, INFINITE); CloseHandle(hDriver);
    CloseHandle(hConductor); getchar();
    return 0;
    }
      

  8.   

    我好笨啊,都看不懂PS: 
    我的目标是 ----> ^_^
      

  9.   

    好深奥,,太牛了!=================================
    北京思源计算机培训中心(http://www.ciitc.com)
      

  10.   

    haoa ,不错啊 真的不错啊 我不不是啊多少