الفريق العربي للبرمجةأرشيف المنتديات · 2000 – 2023
نسخة أرشيفية للقراءة فقط — التسجيل والمشاركة مغلقان، والمحتوى محفوظ كما كان.

جديد Qt في تعدد المسالك

بدأه مصفوفة في 14 ديسمبر 2008 · 5 رد · 1,923 مشاهدة · في قسم Cross Platform GUI Libraries العام
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

السلام عليكم

بسم الله الرحمن الرحيم

لقد تحدث في مقالات سابقة عن تعدد المسالك ولكن هذه المرة سوف أتحدث عن أمور لم أتحدث عنها مسبقا تساعدك في بناء برامج متعددة المسالك تتميز بأداء عالي وسطور أقل

قبل أن أتحدث عن ماهو جديد Qt في تعدد المسالك "Qt4.4" فإنه من الأفضل القاء نظرة على مصطلحات تجدها كثيرا في QtAssistant وهي reentrant functions و thread-safe function و reentrant/safethread classes وماذا يعني إستخدام هذه الدوال أو الفئات داخل برامج متعددة المسالك :-

Reentrant functions

1- يتم استدعائها في نفس الوقت من قبل عدة مسالك

2- كل استدعاء يشير الى بيانات مختلفة (حتى لايحدث تضارب في المصادر وإلا فإن النظام يرسل رسالة خطأ).

Thread-safe functions

1- يتم استدعائها في نفس الوقت من قبل عدة مسالك .

2- كل إستدعاء يشير الى بيانات مختلفة .

3- في حال المشاركة في مصار البيانات فإنه يتم الوصول لها بشكل متسلسل .

Reentrant or thread-safe functions

جميع الدوال بإستثناء الساكنة إما ان تكون reentrant functions او thread-safe functions .

لاحظ أن thread-safe تعتمد دوالها على أحد مبادئ التزامن لتلافي الإشتراك في مصدر واحد للبيانات في نفس الوقت .

ملاحظة قبل البدئ في المقال فجميع ما سوف يتم شرحه يتوفر مع إصدارات Qt4.4 فإذا كنت تملك إصدار سبق هذا الإصدار فإن الأمثلة لن تعمل معك .

1-إدارة مجموعة مسالك بإستخدام الفئة QthreadPool .

في جميع ماشرحته مسبقا كنا ندير كل مسلك على حدى ولكن هذه المرة سوف نرى كيف بإمكاننا إنشاء مجموعة مسالك تدار سويا بشكل سلس ومبسط .

فيما سبق كنا نرث الفئة Qthread ثم نعيد تعريف الدالة run لكي ننشئ مسلك جديد ولكن هذه المرة سوف نرث من الفئة QRunnable وتعيد تعريف الدالة run وهو ماسوف يتم تنفيذ جميع مابداخله ويمكنك أيضا تحديد فيما أردت أن تسمح ل QthreadPool بحذفها بعد تنفيذ ما بداخلها أو لا بإستدعاء الدالة setAutoDelete حيث القيمة true تسمح لها بحذفها و false لا تسمح .

بعدما قمنا بإنشاء فئة جديدة ترث من الفئة Qrunnable فإنه بإمكانك الآن إضافتها الى QthreadPool لكي يجعلها تعمل في مسلك فريد يقوم هو بإدارته وذلك بإستدعاء الدالة start او tryStart حيث تدخل في وسيطها متغير الفئة التي قمت بإنشائها بالوراثة من Qrunnable .

أنظر المثال :-

1-	#include <QtGui>
2-	class myThread:public QRunnable{
3-	public:
4-	myThread(QString s);
5-	void run();
6-	QString st;
7-	};
8-	myThread::myThread(QString s):st(s){
9-	}
10-	void myThread::run(){
11-	int i=3;
12-	while(i){
13-	qDebug()<<st;
14-	i--;
15-	}
16-	}
17-	int main(int argc, char *argv[])
18-	{
19-	QApplication a(argc, argv);
20-	myThread* firstThread=new myThread("first");
21-	myThread* secondThread=new myThread("second");
22-	QThreadPool::globalInstance()->setMaxThreadCount(1);
23-	QThreadPool::globalInstance()->start(firstThread);
24-	QThreadPool::globalInstance()->start(secondThread);
25-	return a.exec();
26-	}

في الأسطر من 2 الى 15 قمنا بإنشاء الفئة myThread الت ترث من QRunnable ثم قمنا بإعادة تعريف الدالة run ثم وفي الدالة main والأسطر من 20 الى 25 قمنا ببالتصريح عن متغيرات الفئة التي أنشأناها ثم أستخدمنا الدالة setMaxThreadCount وهي أحد طرق إدارة تعدد المسالك وذلك بالسماح لعدد معين من المسالك بالعمل في وقت واحد وفي حال تم الإنتهاء من أحدها أو جميعها يتم أخذ مجموعة أخرى من المسالك لتنفيذها في حال كان ما بداخل الوسيط 0 او -1 فإن عدد المسالك التي تعمل دفعة واحدة يساوي عدد المسالك التي يمكن إنشاءها في المعالجات الرئيسية والتي يمكن معرفتها بإستدعاء الدالة QThread::idealThreadCount ثم أخيرا قمنا بتنفيذ العمليات بإستخدام الدالة start فيصبح ناتج العملية كالتالي :-

First 
First
First
Second
Second
Second

لاحظ أن النواتج لم تكن مشعثرة بل بدأ بتنفيذ المسلك الأول وحين أنتهى منه بدأ بتنفيذ المسلك الثاني وربما يبدأ بالمسلك الثاني وحين ينتهي منه ينتقل للأول فهو سماح عشوائي .

حالة الإنتظار QwaitCondition

توفر لك طريقة أخرى للتزامن بالإضافة لطرق سابقة تحدث عنها مقال سابق

ولكن التزامن هنا على شكل إنتظار مؤقت وفك الإنتظار المؤقت بالإضافة أن هذا الإنتظار سوف يسمح لجميع ما أقفل عليه ال mutex قبل تنفيذه بالتنفيذ ويبقى الذي دخل mutex وأقفله ينتظر ليقفل على الآخرين فيما لو أنتهى وقت الإنتظار ويبدأ هو بتنفيذ مابداخله بمعنى آخر هو عكس مؤقت لعملية mutex أنظر المثال :-

1-	#include <QtGui>
2-	QMutex mutex;
3-	QWaitCondition wc;
4-	class myThread:public QThread{
5-	public:
6-	myThread(QString s);
7-	void run();
8-	QString st;
9-	};
10-	myThread::myThread(QString s):st(s){
11-	}
12-	void myThread::run(){
13-	int i=5;
14-	while(--i){
15-	mutex.lock();
16-	wc.wait(&mutex,1000);
17-	qDebug()<<st;
18-	mutex.unlock();
19-	}
20-	}
21-	class myThread2:public QThread{
22-	public:
23-	myThread2(QString s);
24-	void run();
25-	QString st;
26-	};
27-	myThread2::myThread2(QString s):st(s){
28-	}
29-	void myThread2::run(){
30-	int i=5;
31-	while(--i){
32-	mutex.lock();
33-	qDebug()<<st;
34-	mutex.unlock();
35-	}
36-	}
37-	int main(int argc, char *argv[])
38-	{
39-	QApplication a(argc, argv);
40-	myThread* firstThread=new myThread("first");
41-	myThread2* secondThread=new myThread2("second");
42-	myThread2* second2Thread=new myThread2("second2");
43-	firstThread->start();
44-	secondThread->start();
45-	second2Thread->start();
46-	return a.exec();
47-	}

المخرجات

"second" 
"second2" 
"second" 
"second2" 
"second" 
"second2" 
"second" 
"second2" 
"first" 
"first" 
"first" 
"first"

لاحظ بأن ما يفترض أن ينفذ أولا أصبح ضحية هذه الفئة

ويمكنك أيضا القيام بإيقاف الإنتظار بإستخدام أحد الدالتين wakeOne او wakeAll ويشترط عند استخدام الدالة wait أن يكون ال mutex المرسل له كوسيط مقفل عليه .

بسم الله الرحمن الرحيم

مدونة دوال

كيوتي العربي

#2

عليكم السلام

موضوع ممتاز اخي

ممكن اقتراح و ما تعصب :happy:

بـتحاول تكتب الشيفرات بالـ tag الخاص المطوّر, هيك

  1.  
  2. /* Put your code within gcode tags.
  3. as the following:
  4. [gcode = cpp]
  5. //your code goes here...
  6. [./gcode]
  7. Just delete the full stop symbol(the dot) in the ending tag.
  8. I've put it just as a tricky way to avoid any interpreting operation by the interpreter.
  9. */
  10.  
  11. #include <iostream>
  12. using namespace std;
  13.  
  14.  
  15. int main()
  16. {
  17. cout << "Hi there!" << endl;
  18. return 0;
  19. }
  20.  
  21.  
  22.  

يعني افضل و بترتاح من كتابة الأرقام يدوياً, واسهل للقراءة و النسخ و اللصق مباشرة بالمحررات الخاصة للتطبيق, و بتقدر تستعمل مفتاح tab مباشرة داخل الدوال لتنسيق الشيفرة.

موفق يارب

سبب التعديل: اخطاء مطبعية بالشيفرة حساسة شوي

تم تعديل هذه المشاركة بواسطة رغـد في 15 ديسمبر 2008 في 07:39

[وسط]

♥ Countess ♥

57899411.gif

♥

[/وسط]

#3

ولكن أنا كتبت الموضوع في منتدى Qt-ar ومن ثم نسخته الى هذا المنتدى فال tags هنا هو القاسم المشترك بين هذا المنتدى وموقع Qt-ar

عموما سوف آخذ نصيحتك في الإعتبار

وشكرا لكي

بسم الله الرحمن الرحيم

مدونة دوال

كيوتي العربي

#4

أختى العزيزة رغد ،،

أنا معك أختى رغد أن Gcode tag يظهر الكود بشكل سليم جداً و واضح جداً لكن على حساب استخدام الأعضاء للكود .

استخدام Gcode tag لا يعمل بشكل سليم 100% مثل code tag ، لأن gcode يظهر مشاكل عند النسخ (الان جربته ، لا ينسخ أصلاً باستخدام

"انسخ الكود") و عند عمل select لكل الكود تظهر علامات # عند بداية الأسطر الفارغة .

الكود الذى وضعتيه يظهر بهذا الشكل :

#
/* Put your code within gcode tags.
#
as the following:
#
[gcode = cpp]
#
//your code goes here...
#
[./gcode]
#
Just delete the full stop symbol(the dot) in the ending tag.
#
I've put it just as a tricky way to avoid any interpreting operation by the interpreter.
#
*/
#

#
#include <iostream>
#
using namespace std;
#

#

#
int main()
#
{
#
cout << "Hi there!" << endl;
#
return 0;
#
}
#

#

#

توجد العديد من المشاكل فيه ، لذلك تجدين بعض الأعضاء لا يستخدموه (أعتقد رأى الأخ محمد "مصفوفة" مثلى)

هناك حل بسيط ، فى برنامج Code::Blocks ، هناك Plug-in جاهز أسمه Source Code formatter (AStyle) وظيفته عمل Auto-Intend لأجزاء الكود و تنسيقها بشكل جيد ، أنا لا استطيع الأستغناء عن هذا الـ Plug-in ، من الممكن استخدام هذا الـ Plug-in ثم نسخ الكود ووضعه فى code tag حتى يظهر بشكل سليم .

ما رأيك فى هذه الفكرة ؟ :)

هناك حل ظريف اخر ، وضع الكود فى GCode tag ، ثم رفع ملفات الأكواد فى المرفقات الخاصة بالموضوع ، لكن أنا لا اتعلم طريقة عمل الكود و استخدامه إلا عندما أكتبه بنفسى :(

وفقكم الله ،،

#5

رأيي أن القارئ الذ يريد أن يستفيد من الموضوع سوف ينسخ الكود على البيئة او محرر الأكواد ويجربها وبالتأكيد عند التجربة سوف يقرأ الكود من البيئة او محرر الأكواد وليس من الموضوع ...

بالنسبة للترقيم أنا كتبت الموضوع على ملف doc قبل وضعه في المنتدى فالترقيم هناك تلقائي ومريح ثم قمت بنسخه في المنتدى ...

ثم شاكرا لكم إقتراحاتكم ومداخلاتكم ...

بسم الله الرحمن الرحيم

مدونة دوال

كيوتي العربي

#6

بالنسبة للمشكلات التى تحدث عنها اخى عمر فكنت اظن انها من نصيب مستخدمين اللينكس فقط ولكن اتضح الامر انه عيب فى الاسكربت

amdvsintel22.jpg

--i use AMD--

لا اله الا الله محمد رسول الله

أستعن بالله و لا تعجز

تابعنى على تويتر

***

مواضيع مشابهة