# Native Code > برنامه نویسی با C > برنامه نویسی در محیط QT و هم خانواده هایش >  چطو از QTimer و tTcpSockey و   کلاسهای دیگر Qt در QThread استفاد کنیم

## behnia_k

با سلام
من با 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

> با سلام
> من با 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");
    //
    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

اگر از QObject ارث بری کرده باشید و Q_OBJECT رو توی کلاس خودتون گذاشته باشید. بله این روش جواب می ده

----------


## behnia_k

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

----------


## pswin.pooya

> حال اگز بخواهیم سیگنالی از یکی از این ابجکتها را به اسلاتی از دیگری متصل کنیم پارامتر آخر connect را باید چه چیز مشخص کنیم.
> اگر برنامه را به شکل بالا بنویسیم آیا واقعا چند ترد اجرا میشوند یا آنرا شبیه سازی میکند.


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

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

----------


## behnia_k

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


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

----------


## pswin.pooya

اگر تعداد سوکت شما زیاد هست یه ThreadPool ایجاد کنید و از یه ترد اصلی درخواستها رو برای تردهای کارگر ارسال کنید. و یا حتی تردهای کارگر می تونن روی یه صف تولید کننده مصرف کننده ترد سیف (Thread Safe) لاک کنن. 

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


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

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

----------


## pswin.pooya

راستی برای ThreadPool هم کیوت یه کتابخونه داره که من ازش استفاده نکردم اما اصولا باید جواب کار شما رو بده:

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

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

http://doc.qt.io/qt-5/qtcore-threads...producer-class

----------


## negative60

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

----------


## pswin.pooya

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


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


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

----------


## negative60

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


بله درسته بهترین گزینه تو لینوکس epoll هست




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


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

----------


## pswin.pooya

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

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

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

----------


## behnia_k

با تشکر از دوستان
برنامه رو روی سرور لینوکسی اجرا میشه
آیا epoll میتواند جایگزین QSocket شود
ارتباط فقط داخلی نیست و گاهی از سیستم دیگری میخواهند به سوکتی روی سرور ما وصل شوند در این مورد به جای QSocket چه چیری پیشنهاد میدهید

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

----------


## negative60

تو لینوکس epoll بهترین پرفورمنس رو داره امکان مالتی تردینگ هم تو خودش داره و دیگه لازم نیست برای هر سوکت یک ترد بسازید اما کار باهاش کمی‌ مشکل و وقت گیره 
کتابخونه های دیگه هم هستند که میتونید از اونها استفاده کنید مثل libevent, libuv ,POCO و... این کتاب خونه ها کراس پلتفرم هستند و تو ویندوز هم میتونید استفاده کنید
اگر تعداد کانکشنهای همزمان خیلی‌ زیادی ندارید میتونید از همین کیوت استفاده کنید چون هیچکدوم از این کتابخونه‌ها که معرفی‌ کردم به سادگی و راحتی‌ کیوت نیستند

----------


## pswin.pooya

پرفرمانس Boost.Asio از بقیه بالاتره. اما اگر بتونید برنامه نویسی خوب بکنید هیچ کدوم به همون API خود لینوکس نمی رسه.

----------


## behnia_k

> تو لینوکس epoll بهترین پرفورمنس رو داره امکان مالتی تردینگ هم تو خودش داره و دیگه لازم نیست برای هر سوکت یک ترد بسازید اما کار باهاش کمی‌ مشکل و وقت گیره 
> کتابخونه های دیگه هم هستند که میتونید از اونها استفاده کنید مثل libevent, libuv ,POCO و... این کتاب خونه ها کراس پلتفرم هستند و تو ویندوز هم میتونید استفاده کنید
> اگر تعداد کانکشنهای همزمان خیلی‌ زیادی ندارید میتونید از همین کیوت استفاده کنید چون هیچکدوم از این کتابخونه‌ها که معرفی‌ کردم به سادگی و راحتی‌ کیوت نیستند


یکی دو بار خواستم از  poco استفاد کنم ولی سادگی و راحتی Qt مانع شد  :چشمک: 

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

----------

