Re[2]: Работа с потоками (threads) в MFC
От: RussianFellow Россия http://russianfellow.livejournal.com
Дата: 28.12.16 14:17
Оценка:
Здравствуйте, AlexGin, Вы писали:

AG>Правильнее всего — НЕ завязываться на CWinThread (избыточен он для данной задачи), вызывать _beginthreadex либо AfxBeginThread.

AG>ВАЖНО: и в том и в другом случае "функция, производящая математические вычисления" должна быть глобальной или же статической

То есть если я функцию, которая производит вычисления, помечу как static, то её можно сделать потоковой? И есть ли в этом случае какие-то особенности по работе с такой функцией по сравнению с глобальными потоковыми функциями?
1613 г. = 2024 г.
Re[16]: Как грамотно приостановить и запустить на продолжение поток в MFC
От: Evgeniy Skvortsov Россия  
Дата: 28.12.16 20:44
Оценка:
Здравствуйте, RussianFellow, Вы писали:

RF>Евгений мне написал про другой случай--когда есть цикл (вообще говоря, бесконечный)

Неверно! цикл не бесконечный, он управляется основным потоком, который породил этот поток вычислений. Там можно ожидать хоть 20 событий, зависящих от внешних условий. И только основной поток знает как командовать своими "детьми".
В моём примитивном примере показан общий ход мысли. Вообще настоящий промышленный код будет выглядеть раза в 3 сложнее. Проверка кодов возврата и т.д.
Вообще мне странно писать всё это. По сути я печатаю тут свой авторский перевод справки MSDN, где описано ровно то же, и ссылки на примеры кода с пояснениями я привожу в каждом ответе.
Я уже не раз писал, что практически вся исчерпывающая информация есть в MSDN. Лично я так и научился, читая MSDN, пробуя, ошибаясь, думая, временами задавая вопросы на форумах ...
Всё это наводит на мысль, что твой английский настолько плох, что даже не позволяет читать MSDN. И это печально. Я с трудом шпрехаю на инглише, но тех документы читаю достаточно свободно.

Твои же попытки выглядят как у студента горит лаба, учить некогда, заспамлю весь инет своими вопросами. Это я к тому, что ты задаёшь свои вопросы одновременно на нескольких разных сайтах.

Я ещё раз повторю — многопоточность это не самая простая тема, в неё нужно вникать и читать авторитетных людей.

В связи с этим про многопоточность я перестаю отвечать, по причине не понимания тобой базовых принципов.
Без обид.

P.S. Тебе накидали рейтинга и сейчас ты можешь писать в политику. Не видел ни одного сообщения пока, несмотря на заявления.
Re[16]: Как грамотно приостановить и запустить на продолжение поток в MFC
От: Evgeniy Skvortsov Россия  
Дата: 28.12.16 20:53
Оценка:
Здравствуйте, RussianFellow, Вы писали:

RF>Ну, например, делаются какие-то вычисления. Результаты выводятся в консольное окно (никакие другие ресурсы при этом не захватываются). Это консольное окно находится на заднем плане экрана--а на переднем плане находится диалоговое окно приложения. И если пользователь хочет посмотреть процесс вычислений, то при нажатии на кнопку диалогового окна на передний план экрана помещается консольное окно, в которое выводятся результаты вычислений--пользователь видит, что было вычислено к текущему моменту. А потом, при нажатии на другую кнопку диалогового окна, это диалоговое окно опять помещается на передний план экрана, а процесс вычислений продолжается.


Это классический пример неверного проектирования логики ПО.
Если есть два окна, пользователь может сам ткнуть мышью и вызвать окно на первйй план.
По поводу принудительного всплывания недавно была тема в WINAPI, там всё разложили по полочкам.

В общем, нужно учить матчасть.
Re[17]: Как грамотно приостановить и запустить на продолжение поток в MFC
От: RussianFellow Россия http://russianfellow.livejournal.com
Дата: 29.12.16 06:10
Оценка:
Здравствуйте, Evgeniy Skvortsov, Вы писали:

ES>Я уже не раз писал, что практически вся исчерпывающая информация есть в MSDN. Лично я так и научился, читая MSDN, пробуя, ошибаясь, думая, временами задавая вопросы на форумах ...

ES>Всё это наводит на мысль, что твой английский настолько плох, что даже не позволяет читать MSDN. И это печально. Я с трудом шпрехаю на инглише, но тех документы читаю достаточно свободно.

Мой английский неплохой. Просто MSDN--это одно, а объяснение того, что написано в MSDN--это другое. И примеры кода не всегда на MSDN есть.

ES>Твои же попытки выглядят как у студента горит лаба, учить некогда, заспамлю весь инет своими вопросами. Это я к тому, что ты задаёшь свои вопросы одновременно на нескольких разных сайтах.


Ну да, правильно, времени у меня мало.

ES>Я ещё раз повторю — многопоточность это не самая простая тема, в неё нужно вникать и читать авторитетных людей.


ES>В связи с этим про многопоточность я перестаю отвечать, по причине не понимания тобой базовых принципов.

ES>Без обид.

ES>P.S. Тебе накидали рейтинга и сейчас ты можешь писать в политику. Не видел ни одного сообщения пока, несмотря на заявления.


Что же, спасибо. Боюсь, что меня забанят в разделе "Политика". Или за нарушение правил форума (например, "разжигание межнациональной ненависти"), или просто за то, что модераторам не понравится то, что я пишу.
1613 г. = 2024 г.
Re[18]: Как грамотно приостановить и запустить на продолжение поток в MFC
От: aloch Россия  
Дата: 29.12.16 23:01
Оценка: +1
Здравствуйте, RussianFellow, Вы писали:

RF>Здравствуйте, Evgeniy Skvortsov, Вы писали:


RF>Мой английский неплохой. Просто MSDN--это одно, а объяснение того, что написано в MSDN--это другое. И примеры кода не всегда на MSDN есть.


Тебе уже сказали — почитай Рихтера прежде чем лезть к потокам и писать глючный софт. http://wm-help.net/books-online/book/59464.html 0 — там главы 6-11. Уж сто раз бы прочитал, чем спрашивать на форуме.


Re[3]: Работа с потоками (threads) в MFC
От: Evgeniy Skvortsov Россия  
Дата: 30.12.16 09:39
Оценка: 6 (1)
Здравствуйте, RussianFellow, Вы писали:

RF> То есть если я функцию, которая производит вычисления, помечу как static, то её можно сделать потоковой?

Да

RF> И есть ли в этом случае какие-то особенности по работе с такой функцией по сравнению с глобальными потоковыми функциями?


Функция член класса с модификатором static ни чем не отличается от глобальной, кроме того что находится в пространстве имени класса.

Все обычные функции члены класса вызываются со скрытым указателем на экземпляр класса
То есть если есть класс
struct A {
  int m_a;
  void f() {m_a++;}
  static DWORD WINAPI MyThreadFunc(LPVOID lpParam) {return 0;}
};

То при вызове функции f(), на самом деле вызов идёт как f(this) и поэтому внутри функции можно обращаться к переменным, в частности к m_a.
А вот внутри MyThreadFunc — обращаться к m_a уже нельзя. Так как статические функции вызываются так, как они объявлены, this не передаётся.
Но ей передаётся lpParam, поэтому при создании потока можно передать this явно
AfxBeginThread(MyThreadFunc, this)


А в функции потока использовать указатель на экземпляр класса
DWORD WINAPI MyThreadFunc(LPVOID lpParam) {
  A *a = static_cast<A*>(lpParam);
  а-> вызываем что угодно
  return 0;
}


Можно сделать из MyThreadFunc функцию переходник, которая будет звать через указатель нормальную функцию член, в которой можно спокойно работать с данными класса
struct A {
  int m_a;
  void f() {m_a++;}
  static DWORD WINAPI MyThreadFunc(LPVOID lpParam);
  DWORD RealThreadFunc(){};
};
DWORD WINAPI A::MyThreadFunc(LPVOID lpParam) {
  A *a = static_cast<A*>(lpParam);
  return а->RealThreadFunc();
}


Обрати внимание, статические функции должны определяться с указанием имени класса.
Вкратце так.
Отредактировано 30.12.2016 11:24 Evgeniy Skvortsov . Предыдущая версия .
Re[3]: Работа с потоками (threads) в MFC
От: AlexGin Беларусь  
Дата: 30.12.16 09:46
Оценка:
Здравствуйте, RussianFellow, Вы писали:

RF>Здравствуйте, AlexGin, Вы писали:


AG>>Правильнее всего — НЕ завязываться на CWinThread (избыточен он для данной задачи), вызывать _beginthreadex либо AfxBeginThread.

AG>>ВАЖНО: и в том и в другом случае "функция, производящая математические вычисления" должна быть глобальной или же статической

RF>То есть если я функцию, которая производит вычисления, помечу как static, то её можно сделать потоковой? И есть ли в этом случае какие-то особенности по работе с такой функцией по сравнению с глобальными потоковыми функциями?


Пометить как "static" — возможно вызовет ошибку компиляции, т.к. не должно быть прямого обращения к мемберам класса внутри.
Глобальные функции, также как и статические — НЕ ЯВЛЯЮТСЯ ЧЛЕНАМИ КЛАССА.
Все особенности определяются именно данным моментом.

P.S. Здесь чуть выше, товарищ Евгений Скворцов — всё очень толково объяснил!
P.P.S. Книга Джеффри Рихтера: "Создание эффетивных Win-32 приложений..." — это то, что Вам, RussianFellow, нужно!
Отредактировано 30.12.2016 9:51 AlexGin . Предыдущая версия .
Re[4]: Работа с потоками (threads) в MFC
От: pilgrim_ Россия  
Дата: 30.12.16 10:09
Оценка:
Здравствуйте, AlexGin, Вы писали:

AG>Глобальные функции, также как и статические — НЕ ЯВЛЯЮТСЯ ЧЛЕНАМИ КЛАССА.


Не вноси хауос в мозг ТС , конечно же статические методы класса являются его членами, их так и называют: static member_function , но не связанными с экземплярами (объектами) класса.
Отредактировано 30.12.2016 10:31 pilgrim_ . Предыдущая версия .
Re[5]: Работа с потоками (threads) в MFC
От: Слава  
Дата: 30.12.16 10:27
Оценка: :))
Здравствуйте, pilgrim_, Вы писали:

_>Не вноси хаус в мозг ТС

_>хаус
_>хаус

Уместная цитата про рихтера из "Даун хауса"
https://www.youtube.com/watch?v=j2hZgIIaIyI

Давайте посоветуем топикстартеру использовать IOCP. Через него тоже можно таски по потокам раскидывать.
Re[3]: Работа с потоками (threads) в MFC
От: MasterZiv СССР  
Дата: 30.12.16 14:32
Оценка:
Здравствуйте, RussianFellow, Вы писали:

RF>Здравствуйте, _Butch_, Вы писали:


_B_>>std::thread


RF>А если функция, которую я хочу поместить в поток, является членом класса--то как быть?



std::thread это умеет.
Re: Вопросы по функциям _beginthreadex и _endthreadex
От: RussianFellow Россия http://russianfellow.livejournal.com
Дата: 11.01.17 12:12
Оценка:
Я прочитал главы 6--11 книги Джеффри Рихтера "WINDOWS. Создание эффективных WIN32-приложений с учетом специфики 64-разрядной версии Windows" :

http://wm-help.net/books-online/book/59464.html

И у меня возникли два вопроса:

1) Когда вызываем функцию _beginthreadex, то после завершения работы потока (в результате использования функций WaitForSingleObject или WaitForMultipleObjects) обязательно ли следует закрывать дескриптор потока hThread (который был создан функцией _beginthreadex) с помощью функции CloseHandle(hThread); ?

2) Внутри потоковой функции обязательно ли использовать функцию _endthreadex для завершения работы потока или же можно завершить этот поток с помощью return в потоковой функции?

Как я понял, для запуска работы потока лучше всего использовать функцию _beginthreadex, чем функции CreateThread или AfxBeginThread.
1613 г. = 2024 г.
Re[4]: Работа с потоками (threads) в MFC
От: RussianFellow Россия http://russianfellow.livejournal.com
Дата: 11.01.17 12:18
Оценка:
Здравствуйте, AlexGin, Вы писали:

RF>>То есть если я функцию, которая производит вычисления, помечу как static, то её можно сделать потоковой? И есть ли в этом случае какие-то особенности по работе с такой функцией по сравнению с глобальными потоковыми функциями?

AG>
AG>Пометить как "static" — возможно вызовет ошибку компиляции, т.к. не должно быть прямого обращения к мемберам класса внутри.

А что, разве внутри какого-то класса его статическая функция не может обращаться к нестатическим членам (функциям и данным) этого класса?
Вся разница лишь в том, что нестатические функции и данные создаются для каждого объекта класса, а статические функции и данные класса существуют в единственном экземляре--они относятся не к объектам класса, а к самому классу.
1613 г. = 2024 г.
Re[2]: Вопросы по функциям _beginthreadex и _endthreadex
От: Evgeniy Skvortsov Россия  
Дата: 11.01.17 13:34
Оценка: 4 (1)
Здравствуйте, RussianFellow, Вы писали:


RF>1) Когда вызываем функцию _beginthreadex, то после завершения работы потока (в результате использования функций WaitForSingleObject или WaitForMultipleObjects) обязательно ли следует закрывать дескриптор потока hThread (который был создан функцией _beginthreadex) с помощью функции CloseHandle(hThread); ?


Если поток создан при помощи _beginthread и выход из потока осуществляется посредством вызова функции _endthread, то не нужно (она сама закрывает хэндл).
Если поток создаётся с использованием AfxBeginThread, то же не нужно. Там внутри поток создаётся не напрямую, а создается экземпляр класса CWinThread, в деструкторе которого вызывается CloseHandle.

Во всех остальных случаях нужно вызвать CloseHandle, иначе возникает утечка ресурсов.

RF>2) Внутри потоковой функции обязательно ли использовать функцию _endthreadex для завершения работы потока или же можно завершить этот поток с помощью return в потоковой функции?

ExitThread is the preferred method of exiting a thread in C code. However, in C++ code, the thread is exited before any destructors can be called or any other automatic cleanup can be performed. Therefore, in C++ code, you should return from your thread function.

Понятно о чём речь? Кратко — в программах на с++ надо использовать return.

RF>Как я понял, для запуска работы потока лучше всего использовать функцию _beginthreadex, чем функции CreateThread или AfxBeginThread.


_beginthread или _beginthreadex надо использовать если в потоке вызываются какие-то функции CRT.

А вообще Рихтер настоятельно рекомендует использовать _beginthreadex. Что в общем-то логично.
В целом, что бы не забивать голову лишней информацией и избежать всех возможных проблем — правильно использовать _beginthreadex для создания потока и return 0 для выхода из него. С последующим CloseHandle
Отредактировано 11.01.2017 14:38 Evgeniy Skvortsov . Предыдущая версия . Еще …
Отредактировано 11.01.2017 14:28 Evgeniy Skvortsov . Предыдущая версия .
Отредактировано 11.01.2017 14:11 Evgeniy Skvortsov . Предыдущая версия .
Отредактировано 11.01.2017 14:10 Evgeniy Skvortsov . Предыдущая версия .
Re[3]: Вопросы по функциям _beginthreadex и _endthreadex
От: RussianFellow Россия http://russianfellow.livejournal.com
Дата: 11.01.17 14:44
Оценка:
Здравствуйте, Evgeniy Skvortsov, Вы писали:

ES>А вообще Рихтер настоятельно рекомендует использовать _beginthreadex. Что в общем-то логично.

ES>В целом, что бы не забивать голову лишней информацией и избежать всех возможных проблем — правильно использовать _beginthreadex для создания потока и return 0 для выхода из него. С последующим CloseHandle

Ясно, понял. Спасибо!
1613 г. = 2024 г.
Re: Проблема с потоком, работающим с компонентами диалогового окна
От: RussianFellow Россия http://russianfellow.livejournal.com
Дата: 12.01.17 10:11
Оценка:
Есть у меня диалог IDD_CALCMANDIALOG, которому соответствует класс CCalcManDialog.
На этом диалоге расположены кнопки "Остановить", "Продолжить", "Выход" и компонент IDC_STATIC1, которому соответствует переменная m_IDC_STATIC1 типа CStatic.
При открытии этого диалога происходят некоторые действия, которые я поместил в потоковые функции.

Первый вариант--здесь в потоке выводятся в консольное окно числа от 1 до 20000 :

typedef struct
{
  volatile int flag;
} MyStruct;

class CCalcManDialog : public CDialogEx
{
  // данные и методы класса CCalcManDialog;
  MyStruct  myStruct;
  unsigned  threadID;
  HANDLE hThread;
  // методы и данные класса CCalcManDialog;
};

unsigned int __stdcall MyThreadFunc(void* pParam)
{
  int  i;
  MyStruct  *pMyStruct = (MyStruct*)pParam;
  volatile int  *pflag = &(pMyStruct->flag);

  for (i=0; i<20000; i++)
  {
    printf("i = %d\n",i);
    if (*pflag==0)
    {
      printf("The thread was terminated.\n"); // поток был принудительно завершён
      return 0;
    }
    if (*pflag==2) // поток был приостановлен
    {
        while ((*pflag!=0)&&(*pflag!=1))
            Sleep(1000);
        if (*pflag==0)
        {
            printf("The thread was terminated.\n"); // поток был принудительно завершён (после своей приостановки)
            return 0;
        }
    }
  }
  printf("The thread was finished successfully.\n"); // поток завершился благополучно (естественным образом)
  return 0;
}

BOOL CCalcManDialog::OnInitDialog()
{
    CDialog::OnInitDIalog();
    myStruct.flag = 1;
    hThread = (HANDLE)_beginthreadex(NULL,0,&MyThreadFunc,&myStruct,0,&threadID);
    return TRUE;
}

void CCalcManDialog::OnBnClickedOk()
// если была нажата клавиша "Выйти"
{
    myStruct.flag = 0;
    WaitForSingleObject(hThread,INFINITE);
    CloseHandle(hThread);
    CDialogEx::OnOk();
}


В этом варианте всё работает нормально--при открытии диалога в диалоговое окно выводятся целочисленные значения ( *pflag==1 ), при нажатии на кнопку "Остановить" ( *pflag==2 ) поток приостанавливает свою работу и ждёт либо своего возобновления ( кнопка "Продолжить", *pflag==1 ), либо принудительного завершения ( кнопка "Выйти", *pflag==0 ). Если поток работает и до его завершения была нажата кнопка "Выйти" ( *pflag==0 ), то поток принудительно завершается до своего окончания работы. Если же никаких из этих кнопок не было нажато, то поток выполняется до своего завершения.

Второй вариант--здесь в потоке выводится в окно GUI-диалога, в его компонент IDC_STATIC1 (которому соответствует переменная m_IDC_STATIC1) в цикле сначала надпись "Расчёт выполняется", затем через секунду надпись "Расчёт выполняется.", потом через секунду надпись "Расчёт выполняется . .", после этого через секунду надпись "Расчёт выполняется . . .", далее через секунду надпись "Расчёт выполняется" и т.д.:

class  CCalcManDialog;

typedef struct
{
  CCalcManDialog *pCalManDialog;
  volatile int flag2;
} MyStruct2;

class CCalcManDialog : public CDialogEx
{
  // данные и методы класса CCalcManDialog;
  MyStruct2  myStruct2;
  unsigned  threadID2;
  HANDLE  hThread2;
  void  setTextIntoSTatic(char *s);
  CStatic  m_IDC_STATIC1;
  // данные и методы класса CCalcManDialog;
};

unsigned int __stdcall MyThreadFunc2(void* pParam)
{
  int  i;
  char s[50];
  bool localflag = true;
  MyStruct2 *pMyStruct2 = (MyStruct2*)pParam;
  CCalcManDialog *pCalcManDialog = pMyStruct->pCalcManDialog;
  volatile int *pflag2 = &(pmyStruct->flag2);

  while (localflag==true)
  {
    sprintf(s,"Расчёт выполняется");
    pCalcManDialog->setTextIntoStatic(s);
    Sleep(1000);
    sprintf(s,"Расчёт выполняется .");
    Sleep(1000);
    sprintf(s,"Расчёт выполняется . .");
    Sleep(1000);
    sprintf(s,"Расчёт выполняется . . .");
    Sleep(1000);
    if (*pflag2==0)
    {
        sprintf(s,"Расчёт выполнен");
        pCalcManDialog->setTextIntoStatic(s);
        localflag = false;
        break;
    }
    if (*pflag2==2)
    {
        while ((*pflag2!=0)&&(*pflag2!=1))
            Sleep(1000);
        if (*pflag2==0)
        {
            sprintf(s,"Расчёт выполнен");
            pCalcManDialog->setTextIntoStatic(s);
            localflag = false;
            break;
        }
    }
  }
  return 0;
}

void  CCalcManDialog::setTextIntoStatic(char *s)
{
    m_IDC_STATIC1.SetWindowsTextA(s);
}

BOOL  CCalcManDialog::OnInitDialog()
{
    CDialog::OnInitDialog();
    myStruct2.flag2 = 1;
    myStruct2.pCalcManDialog = this;
    hThread2 = (HANDLE)_beginthreadex(NULL,0,&MyThreadFunc2,&myStruct2,0,&threadID2);
    return TRUE;
}

void  CCalcManDialog::OnBnClickedOk()
{
    myStruct2.flag2 = 0;
    WaitForSingleObject(hThread2,INFINITE);
    CloseHandle(hThread);
    CDialogEx::OnOk();
}


В этом случае у меня запускается поток выводящий бегущую строку (надписи "Расчёт выполняется", "Расчёт выполняется .", "Расчёт выполняется . .", "Расчёт выполняется . . ."), но при нажатии на кнопку "Выйти" в функции CCalcManDialog::OnBnClickedOk на строке WaitForSingleObject(hThread2,INFINITE); у меня программа зависает (ждёт бесконечно долго, хотя я и поставил флаг myStruct2.flag2 равным 0). Если же в этой функции заменить WaitForSingleObject(hThread2,INFINITE); на WaitForSingleObject(hThread2,2000); то программа ждёт две секунды, переходит потом на CloseHandle(hThread); и далее--то есть поток завершается. Но по выходе из функции CCalcManDialog::OnBnClickedOk у меня отладчик проваливается в функцию MyThreadFunc2, где он бьётся в одном из мест, где я проверяю значение flag2 (то есть myStruct2.flag2) на 0.

Как исправить эту ошибку? Как сделать так, чтобы и при работе с GUI-диалогом (его компонентами) мои потоковые функции нормально работали, то есть чтобы происходило нормальное завершение их работы по флагу?
Может быть, как-то по-другому следует вызывать функцию _beginthreadex или же вместо неё следует пользоваться функцией AfxBeginThread или классом CWinThread ?
1613 г. = 2024 г.
Re[2]: Проблема с потоком, работающим с компонентами диалогового окна
От: Evgeniy Skvortsov Россия  
Дата: 12.01.17 11:45
Оценка:
Здравствуйте, RussianFellow, Вы писали:

RF>Как исправить эту ошибку? Как сделать так, чтобы и при работе с GUI-диалогом (его компонентами) мои потоковые функции нормально работали, то есть чтобы происходило нормальное завершение их работы по флагу?


Я так понял ты используешь поток для вывода бегущей строки? Это перебор.
Вообще лезть в оконные дела из другого потока — это не есть гуд и чревато непредсказуемыми последствиями и в частности дедлоками.

В твоём случае бегущую строку лучше реализовать через таймер. То есть запускаешь таймер SetTimer(1000) и обрабатываешь сообщение WM_TIMER. В обработчике уже выводишь текст как нужно. Система сама будет вызывать обработчик через указанный интервал. Когда нужно прекратить вызов таймера — останавливаешь его с помощью KillTimer.

RF>Может быть, как-то по-другому следует вызывать функцию _beginthreadex или же вместо неё следует пользоваться функцией AfxBeginThread или классом CWinThread ?

Это здесь не при чём.
Re[3]: Проблема с потоком, работающим с компонентами диалогового окна
От: RussianFellow Россия http://russianfellow.livejournal.com
Дата: 12.01.17 13:58
Оценка:
Здравствуйте, Evgeniy Skvortsov, Вы писали:

ES>В твоём случае бегущую строку лучше реализовать через таймер. То есть запускаешь таймер SetTimer(1000) и обрабатываешь сообщение WM_TIMER. В обработчике уже выводишь текст как нужно. Система сама будет вызывать обработчик через указанный интервал. Когда нужно прекратить вызов таймера — останавливаешь его с помощью KillTimer.


Ясно. Для того, чтобы запустить таймер, нужно воспользоваться функцией SetTimer, а для того, чтобы выключить таймер, нужно воспользоваться функцией KillTimer:

https://msdn.microsoft.com/ru-ru/library/49313fdf.aspx

https://msdn.microsoft.com/ru-ru/library/sfs37s7c.aspx

http://www.firststeps.ru/mfc/steps/r.php?32

Это у меня работает.

Но как правильно поступить с таймером, если запустил его один раз, потом пользователь нажал на кнопку "Приостановить" (таймер должен остановить свою работу), затем пользователь нажимает на кнопку "Продолжить" (таймер должен заработать заново), а потом пользователь нажимает на кнопку "Выйти" (таймер должен прекратить свою работу)? Как это правильно организовать?
1613 г. = 2024 г.
Re[4]: Проблема с потоком, работающим с компонентами диалогового окна
От: Evgeniy Skvortsov Россия  
Дата: 12.01.17 14:48
Оценка:
Здравствуйте, RussianFellow, Вы писали:

RF>Но как правильно поступить с таймером, если запустил его один раз, потом пользователь нажал на кнопку "Приостановить" (таймер должен остановить свою работу), затем пользователь нажимает на кнопку "Продолжить" (таймер должен заработать заново), а потом пользователь нажимает на кнопку "Выйти" (таймер должен прекратить свою работу)? Как это правильно организовать?


По кнопке "Приостановить" — KillTimer, по кнопке "Продолжить" — SetTimer, по кнопке "Выйти" — KillTimer
Re[5]: Проблема с потоком, работающим с компонентами диалогового окна
От: RussianFellow Россия http://russianfellow.livejournal.com
Дата: 13.01.17 06:53
Оценка:
Здравствуйте, Evgeniy Skvortsov, Вы писали:

ES>Здравствуйте, RussianFellow, Вы писали:


RF>>Но как правильно поступить с таймером, если запустил его один раз, потом пользователь нажал на кнопку "Приостановить" (таймер должен остановить свою работу), затем пользователь нажимает на кнопку "Продолжить" (таймер должен заработать заново), а потом пользователь нажимает на кнопку "Выйти" (таймер должен прекратить свою работу)? Как это правильно организовать?


ES>По кнопке "Приостановить" — KillTimer, по кнопке "Продолжить" — SetTimer, по кнопке "Выйти" — KillTimer


Ясно, спасибо.
1613 г. = 2024 г.
Re: Работа с потоками (threads) в MFC
От: MasterZiv СССР  
Дата: 26.12.17 14:43
Оценка:
Здравствуйте, RussianFellow, Вы писали:

RF>Не подскажете ли, уважаемые коллеги, как лучше всего работать с потоками (threads) в MFC?

RF>Есть функция, производящая математические вычисления. Эта функция большая по длине и её действия происходят в цикле до выполнения некоего условия. Эта функция работает в консольном режиме--ввод и вывод данных там происходит с помощью консольного окна.
RF>Как лучше поместить эту функцию в поток--использовать класс CWinThread, воспользоваться функцией AfxBeginThread или же использовать функции WinAPI для работы с потоками?

Если в потоке не будет общения с MFC, то как угодно, то есть сейчас это значит, что лучше средствами STD.
Если в потоке будет общение с MFC (в чём я сомневаюсь, потому что для расчётов это не нужно), то создавать поток надо средствами MFC, AfxBeginThread

AfxBeginThread помимо всего прочего инициализирует per-thread структуры данных MFC, поэтому создавать поток, из которого будет использоваться MFC, нужно именно через эту функцию (или аналог).
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.