PDA

View Full Version : مشکل استفاده از thread ! این روش چه مشکلی داره و چطور درست می شه !؟



FiACKER
شنبه 10 مرداد 1388, 12:22 عصر
سلام برنامه نویسان عزیز
همونطور که می دونید در استفاده از تردینگ دو راه وجود داره : یکی استفاده از کتابخانه های دلفی و دیگری استفاده از توابع api ویندوز.

به خاطره اینکه با توابع api نیازی به کاره زیادی نیست و با توجه به عجله ای که دارم از api استفاده کردم. به این صورت :


Thread1Handle := CreateThread( nil, 1024, @thrd_Check, nil, 0, Thread1ID );




Procedure thrd_Check;SafeCall;
var
iCHar : Char ;
Begin
for iCHar := 'C' to 'Z' do
.

این کد فقط برای مثاله ولی تابع واقعیه من حلقه ی for داره و به توابع دیگه در دیگر unit ها دسترسی داره !
یه تایمر تویه فرم هست که هر چند ثانیه اینو :

Thread1Handle := CreateThread( nil, 1024, @thrd_Check, nil, 0, Thread1ID );
اجرا می کنه و ترده جدید می سازه !

حالا به نظره شما مشکل از کجاست !؟ از دسترسی به توابع دیگه یا به خاطره اینکه هر چند ثانیه یه بار ترد اجرا می شه !؟

اینم بگم که امکان داره که ترد قبلی هنوز بسته نشده باشه که یه ترد جدید اجرا می شه !

FiACKER
شنبه 10 مرداد 1388, 12:29 عصر
اگه می شه راهه حل هم بدید.
اولین بار هست که دارم از ترد استفاده می کنم و دوستانی که تجربه دارن راهنمایی بفرمایند که از کدوم روشه استفاده از ترد استفاده کنم بهتره !؟

البته من نیاز به دو یا سه ترد دارم که دو ترد کاره سنگینی انجام میدن.
تبخیرتونیم:گیج:

vcldeveloper
شنبه 10 مرداد 1388, 19:28 عصر
حالا به نظره شما مشکل از کجاست !؟
شما مگه در پست بالا از مشکل هم صحبت کردید؟!!


ولین بار هست که دارم از ترد استفاده می کنم و دوستانی که تجربه دارن راهنمایی بفرمایند که از کدوم روشه استفاده از ترد استفاده کنم بهتره !؟
همون کلاس TThread دلفی

tdkhakpur
شنبه 10 مرداد 1388, 22:17 عصر
یه تایمر تویه فرم هست که هر چند ثانیه اینو :


Thread1Handle := CreateThread( nil, 1024, @thrd_Check, nil, 0, Thread1ID );
اجرا می کنه و ترده جدید می سازه !



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

p_ooya
شنبه 10 مرداد 1388, 22:47 عصر
سلام. شرمنده من نگرفتم که مشکل شما چیه. و در زمینه کار با thread هم از کلاس خود دلفی استفاده کردم و مشکلی نداشتم. یه نگاهی به اینجا (http://www.barnamenevis.org/forum/showthread.php?t=79463) و اینجا (http://barnamenevis.org/forum/showthread.php?t=167626) بندازید، اگه مشکل حل نشد، سوالتون رو یکم واضحتر بپرسید، اگر سواد ناقصم کافی بود، با هم یه کاریش می کنیم.

FiACKER
یک شنبه 11 مرداد 1388, 07:43 صبح
سلام
اصلا حواسم نبود ! مشکلو نگفتم ! دوروبرم شلوغه !
چند دقیقه برنامه کار می کنه ولی وقتی کاری رو که به ترد دادم زیاد بشه ، پیغام خطا ظاهر می شه و خروج... به خاطره اندازه بافر نیست !؟ 1024 !؟

اونو بی خیال شدم. از کلاسایه دلفی استفاده می کنم.
ببینین برنامه ی من باید از اول تا اخره کارش یه ترد باز باشه و کارایه تقریبا سنگینی رو انجام بده!

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

حالا مشکل اینجاست که ایا باید تمام توابعی که در این کلاسه ترد نیاز هست و باید بهشون دسترسی داشت رو باید عضو همین کلاسم کنم !؟
اینجوری که نمی شه ! همه ی برنامه م می ریزه به هم ! از syncronize هم نمی شه استفاده کرد ! چون باید یه سری ارگومان رو به اون توابعی که نمی تونم به کلاسه ترد-م اضاف کنم ، پاس بدم و نتیجه ی برگشتی رو استفاده کنم !

اصلا می شه بدونه اینکه توابع مختلف در یونیت های دیگه رو در یک کلاس ترد استفاده کرد !؟
مثلا:



// this is class of thread
procedure thread1.dosomething;
var
a : integer;
begin
a := getfilesize(myFileName);
end;

// this is unit filefunction
procedure getfilesize(filename : string):integer;
begin
end;


ایا امکان پذیره ؟
من دسترسی به سیستم برنامه نویسیم ندارم به خاطره همین اینقدر سوال می کنم.
ببخشید

p_ooya
یک شنبه 11 مرداد 1388, 09:02 صبح
سلام.

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

حالا مشکل اینجاست که ایا باید تمام توابعی که در این کلاسه ترد نیاز هست و باید بهشون دسترسی داشت رو باید عضو همین کلاسم کنم !؟من توی لینک دوم که براتون تو پست قبلم گذاشتم، از توابع زیادی استفاده کردم و مشکلی نبود. البته کار thread (از اینجا به بعد می نویسم "نخ") من زیاد سنگین نبود. راجع به اینکه نمی تونید از synchronize استفاده کنید هم نگران نباشید، راه دیگه ای هم هست. شما در کلاسی که برای نخ نوشته اید، برای ارتباط با سایر فرم های برنامه تون می تونید از سیستم پیام رسانی استفاده کنید. یعنی وقتی برنامه تون به یه شرط خاص رسید به جای اینکه یه متد از خودش رو با symchronize فراخوانی کنه یه پیام به یه فرم دیگه میفرسته و شما می تونید با هندل کردن این پیام ازش استفاده کنید. حقیقتش من الان کم کم باید برم. اما دو نکته رو بگم قبلش. توی دلفی می تونید از یه کلاس آماده نخ استفاده کنید :file>new>other>thread object . نکته دوم اینکه برای اینکه به استفاده از نخ ها مسلط بشید حتماً لینک اول پست قبل منو بخونید. توش نکاتی هست راجع به پارامتر های مختلف کلاس، اولویت نخ و اشکالات رایج. برای کار کردن با سیستم پیام در نخ ها به لینک دوم مراجعه کنید (هر چند که یه مطلب مفید دیگه هم تو تالار دلفی راجع به همین هست). اگه مشکلی بود بگید.

vcldeveloper
یک شنبه 11 مرداد 1388, 21:52 عصر
حالا مشکل اینجاست که ایا باید تمام توابعی که در این کلاسه ترد نیاز هست و باید بهشون دسترسی داشت رو باید عضو همین کلاسم کنم !؟
اینجوری که نمی شه ! عزیز جان، Multi-threaded کردن برنامه اینطوری نیست که شما برنامه را بنویسید، بعدش بهش یک کلاس Thread اضافه کنید، و انتظار داشته باشید که معجزه بشه! شما باید در زمان طراحی برنامه به فکر Multi-threading می افتادید، و برنامه را با همین دید طراحی می کردید.
وقتی بدون دید درست و طرح قبلی برنامه را Multi-threaded می کنید، نه تنها در خیلی از مواقع کارایی بهتر نمیشه، بلکه با انواع و اقسام خطاهای عجیب و غریب مواجه میشید، و دیباگ کردن برنامه براتون مثل جهنم میشه.

FiACKER
چهارشنبه 04 شهریور 1388, 13:07 عصر
ممنون
مسافرت بودم...الان تاپیکو دوباره دیدم.
خب پس اقای کشاورز قضیه ی تکرار کدها کمی کدنویسی رو غیر حرفه ای نمی کنه !؟

منظورم اینه که مشکلی نیست که یک تابع رو در چندین کلاس کپی کنم و تکرار کد...

اقای کشاورز مشکل اینجاست که تقریبا 70 درصد از توابع از توابع دیگه که خودم نوشتم مشتق و اجرا می شن !

چه راه حلی رو پیشنهاد می کنید ؟

samprp
چهارشنبه 04 شهریور 1388, 23:21 عصر
من فکر می کنم اگه یه مثلا تابع رو از داخل یه ترید صدا بزنی کلهم توابع زیر مجموعه و خود تابع هم باید از طریق همون ترید اجرا بشن.
در ضمن اگه استفاده از ترید خود دلفی و کلاساش براتون مشکله به این تاپیک یه سر بزنید چون داخلش یه کمپوننت برا کار با ترید معرفی شده.

FiACKER
پنج شنبه 05 شهریور 1388, 21:24 عصر
what topic
where is it ?

samprp
پنج شنبه 05 شهریور 1388, 22:11 عصر
http://barnamenevis.org/forum/showthread.php?t=152289

FiACKER
دوشنبه 09 شهریور 1388, 11:19 صبح
به نظره من هم tthread خوده تابعی که sync شده و تمامی توابع زیر شاخه ی اون رو در thread جاری قرار میدند.

نظره شما چیه اقای کشاورز ؟
ایا همینطوره که گفتم ؟

vcldeveloper
دوشنبه 09 شهریور 1388, 23:02 عصر
به نظره من هم tthread خوده تابعی که sync شده و تمامی توابع زیر شاخه ی اون رو در thread جاری قرار میدند.

نظره شما چیه اقای کشاورز ؟
تابع چیزی نیست که در یک Thread یا در یک Thread دیگه جا بگیره! Thread یعنی مسیر اجرای دستورات. یک برنامه ممکن هست چندین مسیر برای اجرای دستورات داشته باشه. وقتی Thread ایی اجرا میشه، یک مسیر جدید برای دستورات ایجاد میشه. هر کدی میتونه در این مسیر جدید اجرا بشه، میخواید یک تابع باشه، یا هر چیز دیگه.

TThread کدی را در Thread جاری اجرا نمیکنه! همه Threadهای در حال اجرا جاری هستند! TThread در صورت استفاده از متد Synchronize، کد مورد نظر را در Thread اصلی برنامه اجرا میکنه.

FiACKER
سه شنبه 10 شهریور 1388, 01:22 صبح
O.K !

حالا چه مي شه كرد برايه اين كار !؟

يعني چيكار كنم كه در مواقع استفاده از Synchronize توابعي كه در اين مسير قرار مي گيرند در Thread ه اصلي برنامه اجرا نشوند و به Thread ي كه ما ساختيم منتقل بشه (البته بدونه اينكه اون تابع رو عضو كلاسه Thread ي كه ساختيم ، بكنيم) !؟

ايا با استفاده از شي گرايي پيشرفته در دلفي اين كار امكان پذيره !؟

vcldeveloper
سه شنبه 10 شهریور 1388, 01:40 صبح
يعني چيكار كنم كه در مواقع استفاده از Synchronize توابعي كه در اين مسير قرار مي گيرند در Thread ه اصلي برنامه اجرا نشوند و به Thread ي كه ما ساختيم منتقل بشه (البته بدونه اينكه اون تابع رو عضو كلاسه Thread ي كه ساختيم ، بكنيم) !؟
عزیز جان، اصلا Synchronize برای این اونجا هست که شما کد مورد نظر را در داخل Thread اصلی اجرا کنید، نه در داخل Thread ایی که خودتان ساختید. اگر قرار باشه کد در Thread خودتان اجرا بشه که اصلا نیازی به Synchronize نبود!!

khorsandreza
سه شنبه 10 شهریور 1388, 14:57 عصر
سلام
حالا که بحث Thread در این تایپیک هست من هم یک سوال داشتم
اگر بخواهیم دستورات زیر را در داخل یک ترد قرار بدهیم جکار باید انجام داد




Procedure TCreateRcvDataForm.Insert_MAINADATA_Data;
Var
ExitCtrl :Boolen;
Begin
MainQ.Open;
ProgressBar1.Max := MainQ.RecordCount;
ExitCtrl := True;
While Not MainQ.Eof do
begin
Application.ProcessMessages;
ProgressBar1.StepIt;
SPMainQ.Close;
SPMainQ.UnPrepare;
Try
IF MainQ['NAME'] <> Null Then SPMainQ.Params[0].AsString := MainQ['NAME'];
IF MainQ['FAMLI'] <> Null Then SPMainQ.Params[1].AsString := MainQ['FAMLI'];
SPMainQ.ExecProc;
Finally
SPMainQ.UnPrepare;
End;
MainQ.Next;
IF ExitCtrl = false Then Break;
End;
End;

Mahmood_M
سه شنبه 10 شهریور 1388, 17:39 عصر
Synchronize رو در سایت جستجو کنید ...
در لیست مقالات هم می تونید جوابتون رو پیدا کنید ...

موفق باشید ...

vcldeveloper
سه شنبه 10 شهریور 1388, 18:12 عصر
اگر بخواهیم دستورات زیر را در داخل یک ترد قرار بدهیم جکار باید انجام داد
اینها رو بهتر بود در یک تاپیک دیگه می پرسیدید. در هر حال...

کدهای مربوط به تغییر رابط کاربر (مثل Progressbar) رو باید از کد Thread خارج کنید. این تغییرات باید فقط توسط Thread اصلی اعمال بشند. کوئری شما هم اگر AdoQuery هست، چون از COM استفاده میکنه، باید در زمان شروع Thread، با استفاده از CoInitialize مقداردهی اولیه بشه، و در پایان اجرای Thread هم CoUninitialize فراخوانی بشه. هر دو در یونیت ActiveX هستند.
ما بقی کد را می تونید در متد Execute شی ایی که از TThread می سازید، اجرا کنید.

FiACKER
سه شنبه 10 شهریور 1388, 19:40 عصر
مچكرم اقاي كشاورز...همينطوره كه شما مي گيد.

ولي نگفتيد :

ايا با استفاده از شي گرايي پيشرفته در دلفي اين كار امكان پذيره !؟

كه كدهايي رو كه در ديگر كلاسها و ديگر يونيت ها هستند رو عضو كلاسه Thread خودمان در بياوريم ؟

samprp
سه شنبه 10 شهریور 1388, 22:26 عصر
كه كدهايي رو كه در ديگر كلاسها و ديگر يونيت ها هستند رو عضو كلاسه Thread خودمان در بياوريم ؟
منظوتون از این ثبت نام و عضو گیری و اینا چیه؟
اگه همون اجرای کلاس ها از طریق ترید هست که دو سه پست بالاتر جواب داده شد


تابع چیزی نیست که در یک Thread یا در یک Thread دیگه جا بگیره! Thread یعنی مسیر اجرای دستورات. یک برنامه ممکن هست چندین مسیر برای اجرای دستورات داشته باشه. وقتی Thread ایی اجرا میشه، یک مسیر جدید برای دستورات ایجاد میشه. هر کدی میتونه در این مسیر جدید اجرا بشه، میخواید یک تابع باشه، یا هر چیز دیگه.

vcldeveloper
سه شنبه 10 شهریور 1388, 22:32 عصر
ايا با استفاده از شي گرايي پيشرفته در دلفي اين كار امكان پذيره !؟

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

FiACKER
پنج شنبه 12 شهریور 1388, 10:04 صبح
منظوتون از این ثبت نام و عضو گیری و اینا چیه؟
اگه همون اجرای کلاس ها از طریق ترید هست که دو سه پست بالاتر جواب داده شد

WHAT !
من كي گفتم ثبت نام ؟:کف:




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

به طوره خيلي واضح منظورم اينه كه ايا مي شه يه FUNC or PROC در دو كلاس عضو باشه ؟
يعني علاوه بر اينكه در ديگر كلاسهام از اين FUNC or PROC به راحتي استفاده كنم ، در كلاسه Thread ام هم اونها رو داشته باشم و ازشون استفاده كنم. يا كلاً راه حلي كه بتونه همچين كاري رو انجام بده !

براي جلوگيري از تكرار كد !!
تكرار كد برام مهمه. چطور از اين كار جلو گيري كنم !؟
انتقال اون تابع به كلاسه ترد هم غير ممكنه ! بلكه تكرار كد باشه.
مثلا اون تابع بايد بارها در ديگر بخشهاي برنامه استفاده بشه و يه جا هم در ترد استفاده مي شه.

vcldeveloper
پنج شنبه 12 شهریور 1388, 18:03 عصر
به طوره خيلي واضح منظورم اينه كه ايا مي شه يه FUNC or PROC در دو كلاس عضو باشه ؟
يعني علاوه بر اينكه در ديگر كلاسهام از اين FUNC or PROC به راحتي استفاده كنم ، در كلاسه Thread ام هم اونها رو داشته باشم و ازشون استفاده كنم. يا كلاً راه حلي كه بتونه همچين كاري رو انجام بده !
اسم این کار شی گرایی پیشرفته نیست، بلکه بر باد دادن هر چی شی گرایی هست!


براي جلوگيري از تكرار كد !!
تكرار كد برام مهمه. چطور از اين كار جلو گيري كنم !؟
انتقال اون تابع به كلاسه ترد هم غير ممكنه ! بلكه تكرار كد باشه.
شما مشکل در طراحی دارید، نمیخواید طراحی خودتان را تغییر بدید، بجاش میخواید مفاهیم برنامه نویسی را تغییر بدید!
تابع مورد نظر شما چی هست؟ کارش چیه؟ چرا شی Thread شما نمیتونه اون رو فراخوانی کنه؟

یکی از دلایلی که میگم همینطوری نرید یک Thread بسازید، به خیال اینکه Thread سرعت اجرای برنامه را بیشتر میکنه، همین هست. وقتی سراغ چیزی برید که هنوز مفاهیمش براتون خوب جا نیافتاده، اینطوری سر در گم میشید.

FiACKER
پنج شنبه 12 شهریور 1388, 22:19 عصر
چرا عصباني مي شيد اقاي كشاورز.

بچه (FiaCkeR) كه زدن نداره . غلط كرديم از شما سوال پرسيديم.

من نگفتم شی Thread نمیتونه تابعه ي من رو فراخوانی کنه... اون در ابتداي بحث بود و از كلاسه TThread ه دلفي استفاده كردم و اين مشكل حل شد... و حالا مشكل اينه كه نمي خوام توابع sync شده در ترده اصلي برنامه اجرا بشه كه شما گفتيد پس نبايد از sync استفاده كني ! منم دنباله يه راه حل براي جلوگيري از تكراره كد مي گردم.

مشكله من در اينه كه با حجمه خيلي زيادي از كد طرفم و از اول قرار نبود Thread به كار ببرم و حالا كه مي خوام استفاده كنم اينجوري گير افتادم و نمي خوام كدهام رو تكرار كنم.

من نمي خوام مفاهیم برنامه نویسی را تغییر بدم . فقط ازتون سوال كردم ايا اين كار در دلفي عمليه يا نه.


وقتی سراغ چیزی برید که هنوز مفاهیمش براتون خوب جا نیافتاده، اینطوری سر در گم میشید

دوست عزيز اقاي كشاورز من با تجربه ي هر چند كمي كه در برنامه نويسيايه مختلف داشتم هميشه اينجور ياد گرفتم كه مقاله خوندن فايده نداره و بايد به صورت عملي با اون كار درگير شويد تا بهتر همه چيز جا بيفته برام. البته اينو همه مي گن.
من چيزه زيادي از دلفي نمي دونم ... فقط خيلي ازش خوشم مي ياد و هر جا مي رسم تبليغش مي كنم و به همه پيشنهاد مي كنم يادش بگيرن ! (بعضي ها ميگن شركت سازنده دلفي چقدر پول بهت داده كه مياي اينجوري تبليغ مي كني!)

راستي از اواتر هم منظوره بدي نداشتم ! يعني اون چيزي كه شما فكر كرديد نبود ! براي همين هم گذاشته بودمش.

از كمكه شما و دوستانه عزيز هم ممنون و خواهش مي كنم منو ببخشيد كه باعثه عصبانيت شما و ديگر دوستان شدم.

vcldeveloper
جمعه 13 شهریور 1388, 00:59 صبح
چرا عصباني مي شيد اقاي كشاورز.تا جایی که یادم هست، در هنگام نوشتن آن پست عصبانی نبودم.


من نگفتم شی Thread نمیتونه تابعه ي من رو فراخوانی کنه... اون در ابتداي بحث بود و از كلاسه TThread ه دلفي استفاده كردم و اين مشكل حل شد... و حالا مشكل اينه كه نمي خوام توابع sync شده در ترده اصلي برنامه اجرا بشه كه شما گفتيد پس نبايد از sync استفاده كني ! منم دنباله يه راه حل براي جلوگيري از تكراره كد مي گردم.
هر چند كمي كه در برنامه نويسيايه مختلف داشتم هميشه اينجور ياد گرفتم كه مقاله خوندن فايده نداره و بايد به صورت عملي با اون كار درگير شويد تا بهتر همه چيز جا بيفته برام. البته اينو همه مي گن.باید قبل از اینکه دست به کار بشید، با مبانی تئوری مسئله حداقل آشنا باشید. مثلا در همین زمینه، اگر تحقیق می کردید، می دیدید که بحث Synchronize کردن Thread ها یک بحث گسترده هست، و در هر سیستم عاملی انواع و اقسام ابزارها برای این کار وجود داره. متد Synchronize موجود در TThread یکی از ابتدایی ترین و روش ها هست، ولی تنها روش ممکن نیست. این متد فقط برای راحتی کار برنامه نویس در نظر گرفته شده. برنامه نویس می تونه بجای آن از روش های پیشرفته تری مثل استفاده از Mutex, Critical Section, Semaphore, Event و غیره استفاده کنه، که این روش ها محدودیت متد Synchronize مربوط به کلاس TThread را ندارند. همچنین در نسخه های جدیدتر دلفی دلفی متد Queue هم به TThread اضافه شده، که با استفاده از ارسال پیام به Thread اصلی کار میکنه، و مثل متد Synchronize نیازی به توقف Thread در حال اجرا تا زمان انجام کار مربوطه توسط Thread اصلی نیست.

موضوعاتی که می تونید درباره شان تحقیق کنید:
Thread Synchronization
Thread-safe code
و کلاس TThread دلفی

FiACKER
جمعه 13 شهریور 1388, 12:13 عصر
ممنون اقاي كشاورز.
چَشم حتما به دنبال مطالبي كه گفتين مي رم و در موردشون تحقيق مي كنم.

فكر مي كنم دقيقا پسته قبليتون همون پستي هست كه منتظرش بودم.

اميدوارم به جواب برسم.

نماز و روزه هاتون قبول.