ورود

View Full Version : چطو از QTimer و tTcpSockey و کلاسهای دیگر Qt در QThread استفاد کنیم



behnia_k
یک شنبه 16 آبان 1395, 16:06 عصر
با سلام
من با Qt یک کلاس نوشته ام که در آن از انواع کلاسهای Qt مانند QTimer - QTcpSocket - QUdpSocket - ... استفاده کرده ام .
در main اصلی برنامه میتوانم چند object از این کلاس new کنم و برنامه اجرا خواهد شد.
حال قصد دارم اجرای هر Object توسط یک Thread مدیریت شود چگونه باید این کار را انجام داد.
من از Qt 4 استفاده میکنم


--


#include <QCoreApplication>
#include "myObject.h"


int main (int argc, char **argv)
{
QCoreApplication a(argc, argv);
//
CMyObject *obje1 = new CMyObject("Object 1");
CMyObject *obje2 = new CMyObject("Object 2");
CMyObject *obje3 = new CMyObject("Object 3");
CMyObject *obje4 = new CMyObject("Object 4");
CMyObject *obje5 = new CMyObject("Object 5");
//
return a.exec();
}

behnia_k
یک شنبه 16 آبان 1395, 17:44 عصر
با سلام
من با Qt یک کلاس نوشته ام که در آن از انواع کلاسهای Qt مانند QTimer - QTcpSocket - QUdpSocket - ... استفاده کرده ام .
در main اصلی برنامه میتوانم چند object از این کلاس new کنم و برنامه اجرا خواهد شد.
حال قصد دارم اجرای هر Object توسط یک Thread مدیریت شود چگونه باید این کار را انجام داد.
من از Qt 4 استفاده میکنم


--



#include <QCoreApplication>


#include "myObject.h"
int main (int argc, char **argv)
{
QCoreApplication a(argc, argv);
//
CMyObject *obje1 = new CMyObject("Object 1");
CMyObject *obje2 = new CMyObject("Object 2");
CMyObject *obje3 = new CMyObject("Object 3");
CMyObject *obje4 = new CMyObject("Object 4");
CMyObject *obje5 = new CMyObject("Object 5");
//
return a.exec();
}









من از این روش استفاده کردم آیا درست است

#include <QCoreApplication>
#include "myObject.h"


int main (int argc, char **argv)
{
QCoreApplication a(argc, argv);
//
CMyObject *obje1 = new CMyObject("Object 1");
CMyObject *obje2 = new CMyObject("Object 2");
CMyObject *obje3 = new CMyObject("Object 3");
CMyObject *obje4 = new CMyObject("Object 4");
CMyObject *obje5 = new CMyObject("Object 5");
//
QThread *thr1 = new QThread();
QThread *thr2 = new QThread();
QThread *thr3 = new QThread();
QThread *thr4 = new QThread();
QThread *thr5 = new QThread();
//
obj1->moveToThread(trd1);
obj2->moveToThread(trd2);
obj3->moveToThread(trd3);
obj4->moveToThread(trd4);
obj5->moveToThread(trd5);
//
return a.exec();
}

pswin.pooya
دوشنبه 17 آبان 1395, 10:06 صبح
اگر از QObject ارث بری کرده باشید و Q_OBJECT رو توی کلاس خودتون گذاشته باشید. بله این روش جواب می ده

behnia_k
سه شنبه 18 آبان 1395, 12:07 عصر
از
QObject ارث برده اند.
حال اگز بخواهیم سیگنالی از یکی از این ابجکتها را به اسلاتی از دیگری متصل کنیم پارامتر آخر connect را باید چه چیز مشخص کنیم.
اگر برنامه را به شکل بالا بنویسیم آیا واقعا چند ترد اجرا میشوند یا آنرا شبیه سازی میکند.

pswin.pooya
چهارشنبه 19 آبان 1395, 01:23 صبح
حال اگز بخواهیم سیگنالی از یکی از این ابجکتها را به اسلاتی از دیگری متصل کنیم پارامتر آخر connect را باید چه چیز مشخص کنیم.
اگر برنامه را به شکل بالا بنویسیم آیا واقعا چند ترد اجرا میشوند یا آنرا شبیه سازی میکند.

توی مدل برنامه نویسی که اشیاه به هم به شکل سخت چسبیدن که اگر اشتباه نکنم اصطلاحا tight coupling می گن (یا یه چیز شبیه این). فراخوانی مستقیم توابع داخل تردهای مختلف اشتباه محض هست. شما باید دنبال روشهایی مثل Message oriented design باشید تا مشکلی پیش نیاد. یا اینکه با مکانیزم های قوی همزمانی و IPC کار کنید (که راستش رو بخوایین نه تنها سختر هست و امکان باگ دادن بالاتر میره بلکه توی ویندوز هم این موارد همچین توسعه داده نشدن).

اگر ترد ها جدا دارید سعی کنید کار کنید که اونها کاری باهم دیگه نداشته باشن و یا اینکه توسط یه سیستم مرکزی کنترل بشن. اینجوری خیلی راحتر می تونید سیستمون رو کنترل کنید.

behnia_k
چهارشنبه 19 آبان 1395, 08:50 صبح
ت
اگر ترد ها جدا دارید سعی کنید کار کنید که اونها کاری باهم دیگه نداشته باشن و یا اینکه توسط یه سیستم مرکزی کنترل بشن. اینجوری خیلی راحتر می تونید سیستمون رو کنترل کنید.

توی برنامه هر آبجکت از سوکت ها اطلاعاتی را گرفته و پس از پردازش ممکن است آنرا برای آبجکت دیگری ارسال کتد چه راه حلی پبشنهاد میکنید.

pswin.pooya
چهارشنبه 19 آبان 1395, 12:07 عصر
اگر تعداد سوکت شما زیاد هست یه ThreadPool ایجاد کنید و از یه ترد اصلی درخواستها رو برای تردهای کارگر ارسال کنید. و یا حتی تردهای کارگر می تونن روی یه صف تولید کننده مصرف کننده ترد سیف (Thread Safe) لاک کنن.

تعداد نخ های شما بهتره به اندازه تعداد پردازنده ها (هسته ها) باشه.


البته روشهای بهتر و پیچیده تر وجود دارن که می تونن سیستم رو نه تنها امنتر کنن بلکه مزیتهای دیگه مثل توزیع شدگی نیز براتون فراهم کنن. منتها پیاده سازی این روشها خیلی می تونه سخت باشه و بدتر از اون اینه که در صورت پیاده سازی اشتباه می تونه منبع بیشتر خطاهای سیستم تون باشه (به اصطلاح Error prone می گن). پیاده سازی روشهای پیچیده تر نیاز به مطالعه زیاد و دقت و تست خیلی خیلی زیادی داره. توی این روشها معمولا یه سیستم کامپوننتی طراحی می شه و اشیاء به صورت غیر وابسته باهم ارتباط برقرار می کنن و این ارتباطها از طریق یکسری کانالهای کاملا مدیرت شده انجام می شه که بعضا بهشون سیستم لوله کشی هم گفته می شه. منتها همنطور که گفتم فلسفه پشت سر این روشها پیچیده هست و زمان زیادی رو طلب می کنه که شما اونها رو پیاده سازی کنید و متاسفانه کیوت هیچ امکاناتی رو برای پیاده سازی این روشها براتون فراهم نمی کنه (من کتابخونه دیگه ای هم ندیدم که حالت جامع داشته باشه). البته هیچ امکاناتی که دروغ هست. مثلا QObject و فراخوانی توابع به کمک اسم اونها و یا سیگنالها و ... همه گی اصول اولیه یا بهتره بگم پایه ترین اصول پیاده سازی هستن. و یا QDBus می تونه برای توسعه کانال استفاده بشه (که البته معمولا درست کار نمی کنه و اصلا ویژگیهای یک کانال خوب مخصوصا توی ویندوز رو نداره.).

من خودم توی پروژه PCore Qt می خواستم یه کانال رو بنویسم که خیلی از مزیتهای کانال خوب رو داشت (به جزء Reliability و یکی دو مورد کوچیک دیگه) و کاملا شفاف بود و می تونست این سیستم توزیع شدگی و این سیستمی رو که شما لازم دارین فراهم کنه. منتها به دلیل مرده خواری یکسری و کپی پیست کردن پروژه من به اسم خودشون از انتشارش جلوگیری کردم. حتی یه HttpServer نوشتم که نتایج همزمانی اون خیلی نزدیک به Apache Server خالی (یعنی حتی بدون Php ) بود. شاید در آینده این کلاسها رو منتشر کنم.

pswin.pooya
چهارشنبه 19 آبان 1395, 12:24 عصر
راستی برای ThreadPool هم کیوت یه کتابخونه داره که من ازش استفاده نکردم اما اصولا باید جواب کار شما رو بده:

http://doc.qt.io/qt-5/qthreadpool.html

و اینم برای تولید کننده و مصرف کننده:

http://doc.qt.io/qt-5/qtcore-threads-semaphores-example.html#producer-class

negative60
چهارشنبه 19 آبان 1395, 19:42 عصر
زمانی‌ از ترد استفاده کنید که واقعا دلیل خوبی‌ براش وجود داشته باشه کلاسهای سوکت در Qt به صورت ناهمگام (non-blocking I/O) مدیریت شده اند و نیازی نیست از ترد استفاده بشه, اگر پردازشی در کار نیست مالتی تردینگ نه تنها کمک نمی‌کنه بلکه منابع بیشتری مصرف می‌کنه و پیچیدگی‌ برنامه بالا میره خصوصاً اگر تعداد کانکشنها زیاد باشه این هم در نظر داشته باشید که تقریبا همیشه ساخته شدن ترد بیشتر از خود سوکت منابع مصرف می‌کنه خصوصاً در لینوکس

pswin.pooya
چهارشنبه 19 آبان 1395, 20:32 عصر
زمانی‌ از ترد استفاده کنید که واقعا دلیل خوبی‌ براش وجود داشته باشه کلاسهای سوکت در Qt به صورت ناهمگام (non-blocking I/O) مدیریت شده اند و نیازی نیست از ترد استفاده بشه, اگر پردازشی در کار نیست مالتی تردینگ نه تنها کمک نمی‌کنه بلکه منابع بیشتری مصرف می‌کنه و پیچیدگی‌ برنامه بالا میره خصوصاً اگر تعداد کانکشنها زیاد باشه این هم در نظر داشته باشید که تقریبا همیشه ساخته شدن ترد بیشتر از خود سوکت منابع مصرف می‌کنه خصوصاً در لینوکس

البته اگر سرور روی لینوکس باشه که استفاده از سوکتهای کیوت اشتباه هست (سرعتش کندتر هست و لینوکس امکانات IO بیشتری رو می ده).


فقط یه سوال؟ چطور لینوکس منابع بیشتری استفاده می کنه. من چیزی در این مورد نخوندم.

negative60
چهارشنبه 19 آبان 1395, 21:26 عصر
البته اگر سرور روی لینوکس باشه که استفاده از سوکتهای کیوت اشتباه هست (سرعتش کندتر هست و لینوکس امکانات IO بیشتری رو می ده).
بله درسته بهترین گزینه تو لینوکس epoll هست


فقط یه سوال؟ چطور لینوکس منابع بیشتری استفاده می کنه. من چیزی در این مورد نخوندم.
من هم جایی نخوندم اما به صورت تجربی‌ متوجه شدم, میتونید تفاوت سرعت ساخته شدن تردها و مصرف CPU و رم رو در هر دو سیستم عامل با نوشتن یه برنامه ساده روی یک سیستم با سخت‌افزار یکسان تست کنید

pswin.pooya
چهارشنبه 19 آبان 1395, 22:56 عصر
خب اين مي تونه از خيلي از موارد باشه، از ست كردن فلگها گرفته تا تنظيمات كامپايلر، يه موردي جدي كه وجود داره اينه كه كامپايلر msvc استانداردها رو رعايت نمي كنه، مثلا اپيلوگ و يا پرولوگ رو راحت دستكاري مي كنه و ،،، اين رو زماني كه داشتم روي نرم افزار reliable كار مي كردم توي يه تست تزريق خطا متوجه شدم براي همين به نظر مي رسه كه كدها سريعتر از كامپايلرهاي ديگه كار مي كنن. اما در حقيقت اينطور نيست. البته فقط اين نيست

يه مورد ديگه هم اينه كه كلا ايجاد ترد پشت سر هم اشتباه محض هست، شما بايد حتما از pool و صفهاي كار استفاده كنيد، وگرنه كارايي به شدت افت مي كنه.

امكانات ديگه لينوكسي مثل فورك و ... هم مي تونن براي شما توي اينجور موترد معجزه كنن. به هر دليلي برنامه شما كرش كنه سيستمتون از كار نمي افته و فورا كي تونيد يه نمونه كارگر جديد بسازيد. من عاشق اين قسمت هستم و اينكه اين كارگر ها رو هم مي شه با موتردي مثل پايپ خيلي خوشكل تامين شون كرد

behnia_k
چهارشنبه 26 آبان 1395, 09:26 صبح
با تشکر از دوستان
برنامه رو روی سرور لینوکسی اجرا میشه
آیا epoll میتواند جایگزین QSocket شود
ارتباط فقط داخلی نیست و گاهی از سیستم دیگری میخواهند به سوکتی روی سرور ما وصل شوند در این مورد به جای QSocket چه چیری پیشنهاد میدهید

در ویندوز بجای QSocket چه پبشنهاد میدهید.

negative60
چهارشنبه 26 آبان 1395, 20:50 عصر
تو لینوکس epoll بهترین پرفورمنس رو داره امکان مالتی تردینگ هم تو خودش داره و دیگه لازم نیست برای هر سوکت یک ترد بسازید اما کار باهاش کمی‌ مشکل و وقت گیره
کتابخونه های دیگه هم هستند که میتونید از اونها استفاده کنید مثل libevent (http://libevent.org/), libuv (https://github.com/libuv/libuv) ,POCO (http://pocoproject.org/) و... این کتاب خونه ها کراس پلتفرم هستند و تو ویندوز هم میتونید استفاده کنید
اگر تعداد کانکشنهای همزمان خیلی‌ زیادی ندارید میتونید از همین کیوت استفاده کنید چون هیچکدوم از این کتابخونه‌ها که معرفی‌ کردم به سادگی و راحتی‌ کیوت نیستند

pswin.pooya
چهارشنبه 26 آبان 1395, 21:49 عصر
پرفرمانس Boost.Asio از بقیه بالاتره. اما اگر بتونید برنامه نویسی خوب بکنید هیچ کدوم به همون API خود لینوکس نمی رسه.

behnia_k
شنبه 29 آبان 1395, 11:16 صبح
تو لینوکس epoll بهترین پرفورمنس رو داره امکان مالتی تردینگ هم تو خودش داره و دیگه لازم نیست برای هر سوکت یک ترد بسازید اما کار باهاش کمی‌ مشکل و وقت گیره
کتابخونه های دیگه هم هستند که میتونید از اونها استفاده کنید مثل libevent (http://libevent.org/), libuv (https://github.com/libuv/libuv) ,POCO (http://pocoproject.org/) و... این کتاب خونه ها کراس پلتفرم هستند و تو ویندوز هم میتونید استفاده کنید
اگر تعداد کانکشنهای همزمان خیلی‌ زیادی ندارید میتونید از همین کیوت استفاده کنید چون هیچکدوم از این کتابخونه‌ها که معرفی‌ کردم به سادگی و راحتی‌ کیوت نیستند
یکی دو بار خواستم از poco استفاد کنم ولی سادگی و راحتی Qt مانع شد :چشمک:

تعداد کانکشنهای همزمان زیاد یعنی حدودا چندتا