Потоки. Waitforsingleobject.

Тема в разделе "Общие вопросы по С и С++", создана пользователем sanya923, 26 янв 2011.

  1. sanya923

    sanya923 Гость

    Здравствуйте!
    Помогите пожалуйста решить проблему.
    Читать лучше сразу самый низ кода - большой комент, там в принципе вся проблема и заключена.

    Код (C++):
    // spo1.cpp : Defines the entry point for the console application.
    //

    #include "stdafx.h"
    #include <iostream>
    #include "windows.h"
    #include "stdlib.h"
    #include "stdio.h"
    #include <string>
    using namespace std;

    class TQuery
    {
    /*только public оставил на свое усмотрение*/
    public:
    static TQuery *head,*tail;
    static int count_query,count_obs;
    int p,v,i;
    TQuery *next,*pre;
    TQuery(int p_, int v_, int i_) : p(p_), v(v_), i(i_), next(NULL), pre(NULL)
    {}
    //добавление элемента в очередь
    void Past(TQuery *q)
    {
    count_query+=1;
    TQuery *poisk;
    poisk=head;
    if (tail == NULL)
    {
    tail=q;
    head=q;
    }
    else
    {
    if (q->p>poisk->p)
    {
    poisk->pre=q;
    q->next=poisk;
    head=q;
    }
    else
    {
    if (poisk->next==NULL)
    {
    q->pre=poisk;
    poisk->next=q;
    tail=q;
    }
    else
    {
    while ((q->p<=poisk->p)&&(poisk->next!=NULL))
    poisk=poisk->next;
    if (q->p==poisk->p)
    {
    poisk->next=q;
    q->pre=poisk;
    tail=q;
    }
    else
    {
    q->pre=poisk->pre;
    poisk->pre->next=q;
    poisk->pre=q;
    q->next=poisk;
    }
    }
    }
    }
    }
    //удаление элемента из очереди
    void UdElm()
    {
    TQuery *ud;
    count_obs+=1;
    count_query-=1;
    if (head->next!=NULL)
    {
    head=head->next;
    head->pre->next=NULL;
    }
    else
    {
    StartClear();
    }
    delete ud;
    }
    //обнуление параметров
    void StartClear()
    {head=NULL;tail=NULL;count_query=0;}
    void ObsClear()
    {count_obs=0;}
    };

    HANDLE sp; //для семафора
    HANDLE s_kanal[3]; //для семафоров
    HANDLE uvv[3]; //для устройст(потоков) обслуживающих заявки
    HANDLE a,b; //а-поток поступающих заявок,b-поток опрашивающий устройства
    bool p_kanal[3]; //признак занятости устройства
    TQuery *q_elm_kanal[3]; //для обслуживающихся заявок

    //поток с поступающими заявками
    int fThread1()
    {
    int i=0;
    double p_,v_,t1;
    TQuery *z;
    while (true)
    {
    WaitForSingleObject(sp,INFINITE);
    i+=1;
    p_=rand(); v_=rand(); p_=p_/32768; v_=v_/32678;
    z = new TQuery(unsigned(20*p_+0.5),unsigned(8*v_+0.5),i);
    z->Past(z);
    cout<<"заявка № "<<i<<" встала в очередь (приоритет "<<z->p<<", объем "<<z->v<<", № "<<z->i<<")"<<endl;
    ReleaseSemaphore(sp,1,NULL);
    t1=rand();
    t1=t1/32678;
    t1=1000+2000*t1;
    Sleep(unsigned(t1));
    }
    return 0;
    }

    //поток обслуживающего устройства(три устройства будет)
    int fThread2(int i_)
    {
    double t2;
    while (true)
    {
    WaitForSingleObject(s_kanal[i_],INFINITE);//-------здесь поток виснет--------
    t2=rand(); t2=t2/32678; t2=1000*i_+1000*q_elm_kanal[i_]->v;
    Sleep(unsigned(t2));
    cout<<"  устройство № "<<i_<<" обслужило заявку № "<<q_elm_kanal[i_]->i<<" за "<<unsigned(t2)<<endl;
    p_kanal[i_]=true;
    }
    return 0;
    }

    //поток опрашивающий устройства
    int fThread3()
    {
    int i;
    while (true)
    {
    if (TQuery::count_query!=0)
    {
    for (i=0;i<3;i++)
    {
    WaitForSingleObject(sp,INFINITE);
    if (p_kanal[i])
    {
    p_kanal[i]=false;
    q_elm_kanal[i]=TQuery::head;
    TQuery::UdElm;
    cout<<"  заявка № "<<q_elm_kanal[i]->i<<" поступила на устройство № "<<i<<endl;
    ReleaseSemaphore(s_kanal[i],1,NULL);
    ReleaseSemaphore(sp,1,NULL);
    break;
    }
    ReleaseSemaphore(sp,1,NULL);
    }
    }
    }
    return 0;
    }

    int TQuery::count_obs;
    int TQuery::count_query;
    TQuery * TQuery::head;
    TQuery * TQuery::tail;

    int main()
    {
    TQuery::StartClear; TQuery::ObsClear;
    //поток с поступающими заявками сразу начинает работать поэтому 1
    sp=CreateSemaphore(NULL,1,1,NULL);
    int i;
    for (i=0;i<3;i++)
    {
    /*когда потоки устройств запускаются они должны ждать,
    поэтому 0 поставил*/

    s_kanal[i]=CreateSemaphore(NULL,0,1,NULL);
    p_kanal[i]=true;
    }
    a=CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)fThread1,NULL,NULL,NULL);
    for (i=0;i<3;i++)
    {
    /*здесь виснет при первом заходе(см. fThread2)
    и на второй круг не идет, ну и следовательно и "b" тоже не запускается,
    а в нем как раз ReleaseSemaphore, который должен просигнализировать.
    поток "a" при этом продолжает работать.
    в делфи писал, всё было норм. хотел разобраться с этим же и в с++.
    думается я с потоками где-то налажал, неже ли с семафорами,
    т.к. в делфи для синхронизации также пользовался API, т.е. CreateSemaphore,
    WaitForSingleObject,ReleaseSemaphore, а вот поток создавал подругому, не с
    помощью CreateThread*/

    uvv[i]=CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)fThread2(i),NULL,NULL,NULL);
    }
    b=CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)fThread3,NULL,NULL,NULL);
    return 0;
    }
     
  2. lazybiz

    lazybiz Well-Known Member
    C\C++ Team

    Регистрация:
    3 ноя 2010
    Сообщения:
    1.344
    Симпатии:
    0
    Для потока точка входа определена как:
    Код (C++):
    DWORD WINAPI ThreadProc( __in LPVOID lpParameter );
    если хочешь передать параметры в поток, передавай их через...
    Код (C++):
    HANDLE WINAPI CreateThread(
    __in_opt  LPSECURITY_ATTRIBUTES lpThreadAttributes,
    __in      SIZE_T dwStackSize,
    __in      LPTHREAD_START_ROUTINE lpStartAddress,
    __in_opt  LPVOID lpParameter, <------------------------- вот этот параметр !!!
    __in      DWORD dwCreationFlags,
    __out_opt LPDWORD lpThreadId
    );
    Это: uvv=CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)fThread2(i),NULL,NULL,NULL);
    бред, вообще непонятно как это может работать. Переменную i передавай заместо 3-го NULL с конца.

    Тут: b=CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)fThread3,NULL,NULL,NULL);
    та же лажа только в профиль. Функция fThread3 не принимает параметров, хотя должна.


    fThread1, fThread2 и fThread3 должны быть определены как:
    DWORD WINAPI fThread1( LPVOID lpParameter )
    DWORD WINAPI fThread2( LPVOID lpParameter )
    и
    DWORD WINAPI fThread3( LPVOID lpParameter )
    соответственно.

    Переписывай.
     
  3. sanya923

    sanya923 Гость

    lazybiz, спасибо за совет.
    Я попробовал исправить, но у меня чет как-то не вышло. Решил упростить задачу:
    Код (C++):
    #include "stdafx.h"
    #include <iostream>
    #include "windows.h"
    using namespace std;

    HANDLE h1,h2;
    HANDLE sp1;

    DWORD WINAPI Thread1(LPVOID lpParam1)
    {
    for (int i=0;i<100;i++)
    {

    WaitForSingleObject(sp1,INFINITE);
    cout<<"Potok "<<1<<endl;
    ReleaseSemaphore(sp1,1,NULL);
    Sleep(30);
    }
    return 0;
    }

    DWORD WINAPI Thread2(LPVOID lpParam1)

    {
    for (int j=0;j<100;j++)
    {
    WaitForSingleObject(sp1,INFINITE);
    cout<<"Potok "<<2<<endl;
    ReleaseSemaphore(sp1,1,NULL);
    Sleep(5);
    }
    return 0;
    }

    VOID main()
    {
    sp1=CreateSemaphore(NULL,1,1,NULL);

    h1 = CreateThread(NULL,0,Thread1,NULL,0,NULL);
    h2 = CreateThread(NULL,0,Thread1,NULL,0,NULL);

    int uo;
    cin>>uo;
    }
    Здесь два потока выводят свои номера. Учитывая, что у 2-го задержка меньше, то примерно через каждые пять выводов 2-го должен выводить 1-ый. Но выводит только первый.
    Написал тоже самое в Delphi, всё работает, единственное как я уже говорил, я там потоки создаую по другому, но для синхронизации всё тоже самое использую.
    Ни как не могу понять как тут это работает.

    Добавлено: Всё нашел ошибку, h2 = CreateThread(NULL,0,Thread1,NULL,0,NULL);. Там Thread2 должен быть.
     
  4. lazybiz

    lazybiz Well-Known Member
    C\C++ Team

    Регистрация:
    3 ноя 2010
    Сообщения:
    1.344
    Симпатии:
    0
    Вопрос исчерпан?

    Добавлено: Твой последний код можно даже упростить, заодно это будет пример как можно передать простейщий параметр потоку.
    Код (C++):
    #include "stdafx.h"
    #include <iostream>
    #include "windows.h"
    using namespace std;

    HANDLE h1,h2;
    HANDLE sp1;

    DWORD WINAPI a_thread( LPVOID lpParam )
    {
    int  i_thread = (int)lpParam;
    for (int i=0;i<100;i++)
    {
    WaitForSingleObject( sp1, INFINITE );
    cout<<"Potok "<< i_thread <<endl;
    ReleaseSemaphore( sp1, 1, NULL );
    Sleep( i_thread == 1 ? 30 : 5 );
    }
    return 0;
    }

    VOID main()
    {
    sem = CreateSemaphore( NULL, 1, 1, NULL );
    h1 = CreateThread( NULL, 0, a_thread, (LPVOID)1, 0, NULL );
    h2 = CreateThread( NULL, 0, a_thread, (LPVOID)2, 0, NULL );
    }
     
  5. sanya923

    sanya923 Гость

    lazybiz, спасибо.
     
Загрузка...
Похожие Темы - Потоки Waitforsingleobject
  1. Mady
    Ответов:
    3
    Просмотров:
    1.476
  2. 203
    Ответов:
    4
    Просмотров:
    1.752
  3. Senset
    Ответов:
    0
    Просмотров:
    2.332

Поделиться этой страницей