Comments 37
Спасибо. Когда то давно с этим же сталкивался.
0
Можно было, конечно, пойти по пути наследования какого-нибудь готового класса из таких библиотек как: VCL (классTThread) иди Qt (классQThread), но тогда мы бы ограничивались лишь реализацией одного единственного потока в рамках данного класса. А тут мы получаем возможность реализовывать многопоточные классы, которые с легкостью переносятся на другие платформы.
0
Стоило бы упомянуть что __closure – расширение языка в реализации C++ Builder, подобное лихачество непереносимо и небезопасно.
+3
а не было бы проще это сделать как-то так?
class MyCalc
{
private:
void *HandleThread;
unsigned long IdThread;
int tmp1;
char tmp2;
static DWORD WINAPI ThreadF(void *arg)
{
return ((MyCalc*)arg)->CalculationThread();
}
protected:
unsigned long CalculationThread()
{
/////////
}
public:
MyCalc(int indata1, char indata2)
{
HandleThread = CreateThread(NULL, 0, ThreadF, this, 0, &IdThread);
};
~MyCalc()
{
TerminateThread(HandleThread, NULL);
CloseHandle(HandleThread);
};
};
+7
ваше решение абсолютно справедливо. в своем примере я лишь хотел показать, как сделать потоком метод класса, со всеми плюшками ООП. ваш случай не защищен от вызова функции ThreadF только классом. к тому же она не является его членом, хоть и описана внутри.
0
если ThreadF была бы friend, то да, можно было бы вызвать её из вне класса. в моём примере она является static и находится в блоке private, что как раз и защищает её от вызова из вне и сохраняет её принадлежность классу. по крайней мере в Visual Studio это работет по такому принципу
+1
в C++ Builder ваш пример потребовал необходимого преобразования типов, или же объявления ThreadF как __stdcall. также в вашем случае вы не имеете полного доступа к данным класса непосредственно из потока без указания пренадлежности к объекту класса, поэтому вынужденны делать дополнительный метод. в моем примере достаточно лишь выполнить необходимое преобразование типов для адресов метода и функции, после чего метод становится потоком и может получать беспрепятственный доступ данным класса. к тому же при использовании static при динамическом создании и удалении экземпляра класса есть вероятность, что метод ThreadF останется в памяти, что может грозить некоторыми ее утечками.
-1
__closure — если бы он еще всеми компиляторами поддерживался бы.
Так что да, лучше не занимать любовью себе мозги и передавать указатель на this в аргументе.
Так что да, лучше не занимать любовью себе мозги и передавать указатель на this в аргументе.
0
Тут уже писали — использовать __closure — это читерство! :) Существует стандартный метод — попробуйте использовать такое колдунство, как указатель на метод класса, тогда код станет собираться и работать с любым компилятором.
+1
как уже говорилось выше и в топике, вы можете изменять прототип метода как вам угодно. я лишь показал один из возможных примеров реализации.
0
Ну зачем везде городить ифдефы, если можно сразу всё написать по-человечески?
-1
в чем же тогда заключается не человечность примера из топика, и где вы увидели в нем использование препроцессора?
0
Ну приведите пример без __closure для Visual C++
0
А препроцессоры придется ставить именно для определения компилятора например.
0
а зачем его определять, например, если разработка ведется в конкретной среде с, вполне, явным компилятором, к чему тогда использовать препроцессор для определения его типа, или вы при написании кода одновременно используете множество компиляторов? согласен что его использование возможно для обеспечения кроссплатформенности, но в рабочем проекте, который уже отлажен и написан под вполне конкретные условия, не вижу смысла добиваться кросскомпиляции.
0
>а зачем его определять, например, если разработка ведется в конкретной среде с, вполне, явным компилятором
Так говорят только программисты-неудачники. Увы, но во всех книжках, на всех учебных курсах говорят о том, что нужно писать масштабируемый и переносимый код, чтобы не иметь геморроя в будущем.
Так говорят только программисты-неудачники. Увы, но во всех книжках, на всех учебных курсах говорят о том, что нужно писать масштабируемый и переносимый код, чтобы не иметь геморроя в будущем.
0
Пожалуй, это стоит перенести в блог «Ненормальное программирование».
+1
UFO just landed and posted this here
Бред какой-то
>UPD: данный код генерировался и оттачивался в среде C++ Builder, поэтому в прототипе метода присутствует __closure. изменяя прототип вы можете без больших потерь и изменений использовать данный код в других компиляторах.
Если бы я увидел такое в коде коллеги, послал бы его переписывать всё нафиг.
>UPD: данный код генерировался и оттачивался в среде C++ Builder, поэтому в прототипе метода присутствует __closure. изменяя прототип вы можете без больших потерь и изменений использовать данный код в других компиляторах.
Если бы я увидел такое в коде коллеги, послал бы его переписывать всё нафиг.
0
за union'ы впрочем тоже.
0
Согласен. Всё это вывглядит как кастыли. Но он молодец, что написал статью на хабр. Главное, чтобы он всю критику нормально воспринял. Эта статья с комментариями довольно поучительна!
0
а что не так в них, и вообще во всем что в топике, почему сразу бред? можно увидеть вполне конкретные указания на наличие ошибок или тех мест где бред, или других возможных вариантов решения задачи? интересно было бы прочитать и обоснование ваших выводов.
0
UFO just landed and posted this here
UFO just landed and posted this here
Наверное это можно было бы реализовать следующим образом, только зачем?..
template<typename T>
struct tThrd
{
typedef DWORD(__thiscall T::* PMethod)();
static DWORD WINAPI Function(PVOID pParam)
{
return (((tThrd*)pParam)->pThis->*((tThrd*)pParam)->pMethod)();
};
T* pThis;
PMethod pMethod;
HANDLE Handle;
};
class MyCalc
{
public:
MyCalc()
{
// здесь нет никакой магии :)
MyThread.pThis = this;
MyThread.pMethod = &MyCalc::ThrdHandle;
MyThread.Handle = CreateThread(NULL, 0, MyThread.Function, &MyThread, 0, NULL);
}
~MyCalc()
{
WaitForSingleObject(MyThread.Handle, INFINITE);
CloseHandle(MyThread.Handle);
}
public:
DWORD ThrdHandle()
{
// что-то сумбурно и долго считаем
Sleep(10000);
return 1;
}
private:
tThrd<MyCalc> MyThread;
};
0
Sign up to leave a comment.
Многопоточные классы