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

الثريد

مغلق
بدأه MANSUR في 15 يوليو 2004 · 4 رد · 1,698 مشاهدة · في الأسئلة المجابة
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

في الحقيقة تفضل الاخ chik مشكورا

بطرح موضوع الثريد على الرابط التالي

/index.php?showtopic=43790#

وقال عنه :

اقتباس
فيما يخص حلقات loop مثلا ولا سيما إذا كانت كبيرة أو لا منتهية فالأحسن أن نعملها داخل thread خاص بها وهذا سيقوم بإنجاز ما في الحلقة بشكل يمكن أن نقول مستقل عن البرنامج الرئيسي وهذا يمكن الحلقة من الإشتغال ويمكنك أن تقوم بأشياء أخرى دون أن نحس بأن الحاسوب متوقف.

وحيث ان الموضوع مهم ولكنه جاء تبعا لنقاش حول تحويل المتغيرات فقد احببت ان افرد له موضوعا مستقل لنستفيد جميعا منه

وقد قمت بتتبع الكود لفهمه وخرجت ببعض الاشكالات ارجو ان اجد لها جوابا .

DWORD WINAPI Chik5(LPVOID lpParam)
{
	CString st1="Now Number is Mansur: ";
	CString st2;
	CListBox *list=(CListBox*)lpParam;
	for (int i=0;i< 100000;i++)
	{
  if( i % 1000 ==0)
 	 list->ResetContent();
  st2.Format("%s %d",st1,i);
  list->AddString(st2);
	}
	return 1;
}

وهذا باعتقادي يشبه الـ Function بحيث انه يملك مدخلات وله مخرجات . حيث يتم استدعاءه من خلال الكود القادم

void CThrdDlg::OnWithThread() 
{
	m_list.ResetContent();
  CreateThread(NULL,0,Chik5,&m_list,0,&IdThread);
}

السؤال هو :

DWORD = ؟

WINAPI = ؟

Chik5 = الاسم الخاص بالثريد

(LPVOID lpParam) =اعتقد انها المدخلات ولكن ما نوعها ؟

كذلك الجملة اللتي تنشأ الثريد

CreateThread(NULL,0,Chik5,&m_list,0,&IdThread

ما هي البرميترات المدخله عليها غير الاسم ومكان المخرجات

اشكر لكم تفضلكم بالاجابة ..

#2

يمكن استخدام الدالة البديلة التى تعمل من MFC

CWinThread* AfxBeginThread(YourFunction,void* param,THRAED_PRIORITY,........)

فى الحقيقة انا لا اعرف ما هى بقية المعاملات لكنى استعمل الافتراضى منها

مثلا لنفرض انك قد قمت بانشاء Dialog Based Application

بالاسم Test اذا قمت بقبول الاسماء الافتراضية للمشروع يتوقع ان تكون هناك ال class

الرئيسية التى تمثل الdialog و الاسم هو CTestDlg.

علينا اولا انشاء دالة من النوع static حتى يكون لديها عنوان ثابت

فى العادة انا انشئ هذه الدالة بالاسم StaticRun و الصيغة العامة لها

static UINT StaticRun(void* pVoid)

ثانيا علينا اعداد دالة اخرى

void Run()

الدالة الاخيرة بتم استخدامها للتشعب الجديد لان الدالة الساكنة الاولى

لاتستطيع الوصول الى خصائص كائن معين

مثلا يكمن ان تكتب فى الدالة Run

الكود التالى

while(TRUE)
{
          MessageBox("Just Now has made it");
}

و لكن هذا ليس كافيا و الا كانت الدالة StaticRun لا داعى لها

فى الدالة StaticRun اكتب الكود التالى

CTestDlg* m_this = (CTestDlg*)pVoid;
m_this->Run();
return 0;

بقى الان شئ واحد هو المكان الذى سوف تطلق منه الدالة StaticRun

يمكن ان يكون ذلك من اى دالة فى الCTestDlg class

مثلا عند حدث النقر بالماوس

نكتب الكود

AfxBeginThread(StaticRun,this,THREAD_PRIORITY_NORMAL);

يمكن ان يكون الكلام قد انتهى

اذا وجدت وقت اخر يمكننى ان اريك الطريقة التى يمكن ان توقف منها Run

#3

السلام عليكم

أولاً

DWORD هي DOUBLE WORD و ما هي إلا إعادة تعريف للنمط unsigned long بهذا الاسم

ثانياً

WINAPI هي كلمة تحدد للمترجم كيفية استدعاء هذا التابع أو ما يسمى بال calling conventions و إذا تتبعت تعريفها في ملف windef.h لوجدت أن لها تعاريف متعددة تختلف بحسب نظامك أي أنها تختار النمط المناسب للإستدعاء و على كل حال فلا تقلق إذ أن أي مرجع لتوابع تذكر لك صراحة أيجب استخدام هذه الكلمة أم لا

ثالثاً

كلامك صحيح اسم التابع هو اسم الثريد

رابعاً

نعم هي المدخلات و هي من النمط الذي تريده إي نمط كان لأنك تدخل مؤشر من النوع void الذي يمكنه حمل أي مؤشر آخر و لكن عليك قبل استخدامه (داخل الثريد) أن تعمل له قصر على نمطه الحقيقي أو casting فإذا كان int مثلاً عليك أن :

int param = *((int*) lpParam);

وأما عن تابع انشاء ثريد:

HANDLE CreateThread(
  LPSECURITY_ATTRIBUTES lpThreadAttributes, // SD
  DWORD dwStackSize,                        // initial stack size
  LPTHREAD_START_ROUTINE lpStartAddress,    // thread function
  LPVOID lpParameter,                       // thread argument
  DWORD dwCreationFlags,                    // creation option
  LPDWORD lpThreadId                        // thread identifier
);

الأول يحدد صلاحيات الثريد و إذا كان NULL يجعل الصلاحيات افتراضية

الثاني حجم ال stack المسموح لهذا الثريد بحجزه و استخدامه من الذاكرة و إذا كان صفر أو قيمة أقل من القيمة الافتراضية فيجعله النظام بقدر القيمة الافتراضية

الثالث و الرابع تعرفهم

الخامس خيارات يمكن استخدامها مثلاً يمكنك تمرير القيمة CREATE_SUSPENDED و بذلك يتم انشاء ثريد و لكن مع وقف التنفيذ أي نائم لا يعمل و يمكنك ايقاظه في أي لحظة باستخدام التابع resumeThread()

السادس معرف رقمي يميز الثريد

يعيد التابع في حالة النجاح handle to the thread

على كل حال هذه الأشياء موجودة و موثقة في أي Help أو Reference و من الفائدة يا أخي أن تعتاد على استخدامها فكل ما ذكرته سابقاً مأخوذ من ال MSDN مثلاً

ان شاء الله يكون وصلك ما تريده من اجابة

#4

الف شكر يا شاب

السي مشوارها طويل الله يعيننا ...

اهم شي الصبر والاجتهاد . والتوفيق على الله

#5

السلام عليكم,

أرى أن هذا الموضوع أخذ قسطه من الإهتمام . والثريد بعبارة أخرى يمكن أن نصفه مثل برنامج مستقل يشتغل لوحده ولكن يبقى دائما تحت مضلة Process أو التطبيق الأول. وكما ذكر من قبل يمكن إما أن نستعمل دوال MFC أو دوال API مباشرة وهنا تبقى الصعوبة نسبية وحسب ما ألفنا أن ننجزه وقد تبدو لنا هذه أسهل من تلك وعلى العموم يمكن أن نشغل ما نشاء حسب ما نقوم به.

فيما يخص البارامترات فأضن أن الإخوان ذكروا ما يمكن ذكره وكما نرى رغم أنها تتطلب بارامترات نسبيا كثيرة ولكن يمكن أن نعتمد على Default في الكثير منها .

يبقى ابارامتر أو نوع البارامتر الذي نرسله إلى دالة ثريد وهو من نوع مؤشر ل void وهذا يعني أنه يمكننا إرسال أي نوع وهذه الطريقة نستعملها حين لا نريد أن نتقيد بنوع ما فنرى في المثال السابق أننا أرسلنا بارامتر عبارة عن مؤشر ل CListBox وقد نحتاج في برنامج آخر أن نرسل عددا من نوع int أو ما نحتاجه لبرنامجنا ولهذا نختار void . وطرقة دوال الثريد هي في شكل الدوال الأخرى مثل الدوال المكلفة برسائل النوافذ أو دوال CallBack لدوال Enum أو دوال الهوك وغيرها.

إلى اللقاء.

هذا الموضوع مغلق.

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