PDA

View Full Version : خروج از يك تابع، از بيرون از تابع



FiACKER
دوشنبه 05 مهر 1389, 03:44 صبح
سلام
آيا راهي وجود داره كه مثلا وقتي داريم تويه تابع A يه حلقه بينهايت رو اجرا ميكنيم، از بيرون از تابع A، بريك كنيم و كلان تابع بسته شه ؟

براي مثال :


procedure A();
begin
while AAAA = True do
begin
//some code
//some other code
CheckBreak; //procedure or function, for check end time
end;
end;


اون تابع CheckBreak يك سري شرايط رو چك ميكنه و مواقعي كه بايد از حلقه while AAAA = True do خارج شد. بدونه اينكه من دستور شرطي بكار ببرم، تابع رو Exit كنه.

چطور بايد اين كار رو كرد ؟

vcldeveloper
دوشنبه 05 مهر 1389, 06:28 صبح
کافیه اون CheckBreak یک مقدار Boolean برگردونه که مشخص کنه آیا حلقه باید ادامه پیدا کنه، یا نه؛ همین.

nilidelphi
دوشنبه 05 مهر 1389, 18:21 عصر
سما می تونید اون متغیر AAAA را بصورت سراسری بگیرید و هروقت در هرجای دیگه خواستید
که حلقه اتمام پیدا کنه اون متغیر رو False کنید.

البته این زمانی موثر خواهد بود که شما از متد ProcessMessage یا یک ترد استفاده کنید.

FiACKER
دوشنبه 05 مهر 1389, 23:18 عصر
سلام

ممنون از راهنماييتون
اما بيشتر منظورم خروج از تابع بود ! تا اينكه از اون حلقه.


تابع رو Exit كنه.

براي مثال برنامه من يكسري كار رو انجام ميده تا برسه به تابع CheckBreak ...بعد تويه تابع CheckBreak مدت 10 دقيقه صبر ميكنه كه يه كاري به پايان برسه. اگه اون كار به پايان نرسيد، ميخوام تابعي كه CheckBreak رو صدا زده، به پايان برسه!
راستش برنامه من يه برنامه بانك اطلاعاتي هست كه بايد از اين طريق زمان رو كنترل كنيم. روشه ديگه رو نمي شه در نظر گرفت.


براي اينكار بايد از اشاره گر ها استفاده كرد ؟ يا راهه ديگه اي داره ؟

SAASTN
دوشنبه 05 مهر 1389, 23:23 عصر
خوب بجای Break از Exit استفاده کنید:

begin
while AAAA = True do
begin
//some code
//some other code
if CheckBreak then Exit; //procedure or function, for check end time
end;
end;

tdkhakpur
سه شنبه 06 مهر 1389, 01:43 صبح
اما بيشتر منظورم خروج از تابع بود ! تا اينكه از اون حلقه.
براي مثال برنامه من يكسري كار رو انجام ميده تا برسه به تابع CheckBreak ...بعد تويه تابع CheckBreak مدت 10 دقيقه صبر ميكنه كه يه كاري به پايان برسه. اگه اون كار به پايان نرسيد، ميخوام تابعي كه CheckBreak رو صدا زده، به پايان برسه!
راستش برنامه من يه برنامه بانك اطلاعاتي هست كه بايد از اين طريق زمان رو كنترل كنيم. روشه ديگه رو نمي شه در نظر گرفت.
براي اينكار بايد از اشاره گر ها استفاده كرد ؟ يا راهه ديگه اي داره ؟
دو راه دارید یکی اینکه تابع CheckBreak را داخل نخ(ترد) پیاده سازی کنید و این نخ را داخل تابع A اجرا کنید و در هر نقطه ای از برنامه که باشید میتوانید به نخ پیغام خاتمه را ارسال کنید و یا اینکه مستقیما ترد را متوقف کنید البته در این الگوریتم شما تابع صدا کننده نخ باید تشخیص دهد که نخ به اتمام رسیده است یا نه! به همین منظور یک مقدار که خاتمه نخ را نشان بدهد برای تابع صدا کننده(A) برگشت بدید.
(در این میان برای اینکه cpu دچار حلقه سریع نشه میتوانید توسط WaitMessage منتظر بمانید و برای رهایی از wait هم میتوانید قبل از خاتمه نخ یک پیعام به پنجره اصلی ارسال کنید WaitMessage هم یه اتمام برسد.)
دومین روش کمی پیچیده که اصولی نیست این هست که هر تابعیبه هنگام call شدن آدرس برگشت از تابع را داخل پشته قرار میده تا به هنگام خروج از تابع این ادرسها از پشته خارج شده و جهت cpu را تنظیم کرده و به نقطه اولیه که تابع صدا شده است برگشت شود .

FiACKER
سه شنبه 06 مهر 1389, 01:51 صبح
خوب بجای Break از Exit استفاده کنید:
از if نمي خوام استفاده كنم.
ميخوام از بيرون از تابع exit كنم.

اين توهمي بيش نيست، اما يه چيزي مثله اين :

ExitProcedure( A );
پارامتر A هم كه ام تابع مون هست... يه همچين چيزي :کف:

vcldeveloper
سه شنبه 06 مهر 1389, 07:50 صبح
اين توهمي بيش نيست، اما يه چيزي مثله اين
به نظر میاد شما برای حل یک مسئله به این نتیجه رسیدید که باید همچین کاری کنید. اگر اون مسئله رو مطرح کنید، راحتر به جواب می رسید.
چیزی که شما به عنوان یک مثال ذکر کردید، طبیعتا از داخل یک Thread قابل انجام نیست (اگر از بحث Fiberها صرف نظر کنیم)، چون در یک Thread شما یک مسیر اجرای کد دارید، نمیشه که هم کد اون تابع شما در حال اجرا باشه، و هم کد چک کردن مربوط به خروج از تابع؛ غیر از اینکه اینها در دو Thread مستقل در حال اجرا باشند.

tdkhakpur
سه شنبه 06 مهر 1389, 14:39 عصر
نمیشه که هم کد اون تابع شما در حال اجرا باشه، و هم کد چک کردن مربوط به خروج از تابع؛ غیر از اینکه اینها در دو Thread مستقل در حال اجرا باشند.
نه این شکلی نیست وقتی ترد یک اشاره گر باشه که بیرون ایجاد شده و توسط تابع A استارت شده باشه چرا نشه این کار رو انجام داد؟

vcldeveloper
سه شنبه 06 مهر 1389, 16:25 عصر
نه این شکلی نیست وقتی ترد یک اشاره گر باشه که بیرون ایجاد شده و توسط تابع A استارت شده باشه چرا نشه این کار رو انجام داد؟
"Thread یک اشاره گر باشه" یعنی چی؟ اشاره گر یک نوع داده است، Thread یک مسیر اجرای کد برای سیستم عامل. حالا یک Thread چطور میتونه یک اشاره گر باشه؟!

مابقی بخش های پست هم نامفهوم هستند؛ بیرون کجا ایجاد شده باشه؟ برای اینکه Thread ایی به قول شما توسط تابع A استارت بشه، باید تابع A خودش در داخل یک Thread دیگه در حال اجرا باشه؛ یعنی میشه باز دو Thread وجود دارند.

tdkhakpur
سه شنبه 06 مهر 1389, 18:38 عصر
"Thread یک اشاره گر باشه" یعنی چی؟ اشاره گر یک نوع داده است، Thread یک مسیر اجرای کد برای سیستم عامل. حالا یک Thread چطور میتونه یک اشاره گر باشه؟!


حالا دلفی زیاد با اشاره گر دل خوشی نداره پس مفهوم کار رو به شکل دیگه باید بیان کرد اینکه یک Thread که تابع CheckBreak را در بر داشته بصورت گلوبال تعریف شده و در حین ایجاد فرم ساخته بشه که به حالت suspend قرار داره و پروسه A این ترد را استارت بزنه اونوقت همان مواردی دنبال میشه که تاپیک بالا عرض شد.


برای اینکه Thread ایی به قول شما توسط تابع A استارت بشه، باید تابع A خودش در داخل یک Thread دیگه در حال اجرا باشه؛

به گمانم برای این کار فقط باید استارت بشه و کار دیگه ای برای تابع A باقی نمونه و احتیاجی نیست که A هم جزو یک ترد دیگه باشه تا خاتمه پیدا کنه تنها کاری که پروسه A باید منتظر باشه این هست که گوش کنه کی Thread خاتمه پیدا کرده تا اون هم به کارش خاتمه بده.

FiACKER
سه شنبه 06 مهر 1389, 22:43 عصر
از توضيحاتتون ممنون، اما كليه كارهايي كه من تا حالا انجام دادم، كلي تابعه تو در تو هست و امكان استفاده از ترد وجود نداره. اگه بخوام از ترد استفاده كنم، بايد كليه توابع رو تويه يه كلاس ترد پياده كنم.

vcldeveloper
سه شنبه 06 مهر 1389, 23:17 عصر
حالا دلفی زیاد با اشاره گر دل خوشی نداره پس مفهوم کار رو به شکل دیگه باید بیان کرد اینکه یک Thread که تابع CheckBreak را در بر داشته بصورت گلوبال تعریف شده و در حین ایجاد فرم ساخته بشه که به حالت suspend قرار داره و پروسه A این ترد را استارت بزنه اونوقت همان مواردی دنبال میشه که تاپیک بالا عرض شد.
ربطی به دلفی نداره؛ مفهون اشاره گر و مفهوم Thread ربطی به هم ندارند، میخواد در دلفی باشه، یا در C یا اسمبلی، یا هر زبان برنامه نویسی دیگه.


به گمانم برای این کار فقط باید استارت بشه و کار دیگه ای برای تابع A باقی نمونه و احتیاجی نیست که A هم جزو یک ترد دیگه باشه تا خاتمه پیدا کنه تنها کاری که پروسه A باید منتظر باشه این هست که گوش کنه کی Thread خاتمه پیدا کرده تا اون هم به کارش خاتمه بده.
مشکل شما در درک مفهوم Thread هست؛ همین که Process ایی در سیستم اجرا میشه، یعنی Thread ایی در حال اجرا ست. وقتی شما کدی دارید که میخواید در سیستم اجرا بشه، باید اون کد در داخل یک Thread اجرا بشه. پس وقتی شما می بینید یک برنامه در حال اجرا ست، یعنی یک Thread در حال اجرا ست. نتیجه می گیریم که تابع فرضی A شما، برای اینکه بتونه اجرا بشه، حتی اگر فقط یک خط کد باشه، باید در یک Thread در حال اجرا باشه. حالا اگر این تابع بخواد یک Thread دیگه را که فرضا Suspend بوده، Resume کنه، اون وقت ما با دو Thread سر و کار داریم، نه یک Thread. مشکل شما اینه که فکر می کنید کدی میتونه خارج از یک Thread در حال اجرا باشه، در حالی که همه کدهایی که اجرا میشند، در واقع در داخل یک Thread اجرا میشند.

tdkhakpur
چهارشنبه 07 مهر 1389, 00:06 صبح
اما كليه كارهايي كه من تا حالا انجام دادم، كلي تابعه تو در تو هست و امكان استفاده از ترد وجود نداره. اگه بخوام از ترد استفاده كنم، بايد كليه توابع رو تويه يه كلاس ترد پياده كنم.

نه لازم به این کار نیست شما فقط تابع CheckBreak خودتان را داخل excute ترد قرار بدید(به نظرم قبلا بیان کرده بودید که ممکن هست CheckBreak تا زمان معینی نتواند کار خودش را خاتمه بده و لازم هست طی یک زمان مشخص که کار CheckBreak تمام نشد بتوان از تابع A خارج شد و گفته شد که برای خروج از تابع لازم هست بطور اصولی از آن خارج بشید و یک راه هم پیشنهاد شد.)
اگر متوجه نشدید کدتان را ارسال کنید تا اصلاح بشه.


مشکل شما در درک مفهوم Thread هست؛

اولا من در مورد چیزی که نظری را میگم هیچ مشکلی ندارم و دوما در مورد


وقتی شما می بینید یک برنامه در حال اجرا ست، یعنی یک Thread در حال اجرا ست.

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

مشکل شما اینه که فکر می کنید کدی میتونه خارج از یک Thread در حال اجرا باشه، در حالی که همه کدهایی که اجرا میشند، در واقع در داخل یک Thread اجرا میشند.
من همچین مشکلی دارم؟!!

vcldeveloper
پنج شنبه 08 مهر 1389, 17:41 عصر
معلومه وقتی برنامه لود میشه باید داخل لیست پردازشها قرار بگیره تا اجرا بشه و به هر یک از نودهای این لیست یک ترید میگن ان که ربطی به ترد های ایجاد شده نداره فقط شناسه ترد مربوط به ترد برنامه اصلی میشه.یک Process یک Process هست، و یک Thread هم یک Thread. هر Process برای اجرا نیاز به حداقل یک Thread داره، پس هر Process میتونه حاوی یک یا چند Thread باشه.


به هر یک از نودهای این لیست یک ترید میگن ان که ربطی به ترد های ایجاد شده نداره
اتفاقا مستقیما ربط داره، اگر ربط نداشت، اساسا نوشتن برنامه های Multi-threaded بی معنی میشد!


من همچین مشکلی دارم؟!! متاسفانه بله، با توجه به مطالب زیر که در پست های قبلی همین تاپیک مطرح کردید:


به گمانم برای این کار فقط باید استارت بشه و کار دیگه ای برای تابع A باقی نمونه و احتیاجی نیست که A هم جزو یک ترد دیگه باشه تا خاتمه پیدا کنه

tdkhakpur
پنج شنبه 08 مهر 1389, 19:22 عصر
اتفاقا مستقیما ربط داره، اگر ربط نداشت، اساسا نوشتن برنامه های Multi-threaded بی معنی میشد!


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

متاسفانه بله، با توجه به مطالب زیر که در پست های قبلی همین تاپیک مطرح کردید:

حب باز هم میگم.
یعنی به نظر شما اگر تابعی بخاد یک ترد را استارت بزنه باید جزئی از ترد باشه؟؟!!

vcldeveloper
جمعه 09 مهر 1389, 08:15 صبح
یعنی به نظر شما اگر تابعی بخاد یک ترد را استارت بزنه باید جزئی از ترد باشه؟؟!!
هر کدی برای اجرا شدن باید در داخل یک Thread باشه، مثل این هست که بگیم، واگن های یک قطار برای حرکت، باید بر روی ریل قرار داشته باشند، وگرنه حرکت نمی کنند. کدها هم برای اجرا شدن نیاز به یک مسیر اجرا دارند که سیستم عامل در اختیارشون قرار میده، تا زمانی که این مسیر بهشون داده نشه، اجرا نمیشند. این مسیر فرضی هم فقط یک لاین داره، و نمیشه در آن دو یا چند کد را همزمان با هم حرکت داد.

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

وقتی شما در کد خودتان یک Thread دیگه را شروع می کنید، در واقع از لحظه شروع شدن آن Thread، یک انشعاب در مسیر اجرای کدها ایجاد می کنید، و بخشی از کدهای برنامه را از مسیر آن انشعاب اجرا می کنید. این کار مثل عملکرد خطوط ویژه اتوبوس داخل شهری یا خطوط BRT هست؛ شهرداری برای اینکه اتوبوس های شهری در ترافیک، بین سایر ماشین ها گیر نکنند، خطوط ویژه ایی را برای آنها فراهم میکنه، و اتوبوس ها را در داخل آن خطوط حرکت میده. در این حالت، هم اون ماشین های شخصی داخل ترافیک، هم اتوبوس های شهری دارند در داخل خیابان حرکت می کنند، ولی هر کدام در لاین های خودشان، در نتیجه، ترافیک در لاین ماشین های شخص خللی در حرکت اتوبوس های شهری ایجاد نمی کنه.

tdkhakpur
جمعه 09 مهر 1389, 11:57 صبح
هر کدی برای اجرا شدن باید در داخل یک Thread باشه،
وقتی برنامه شما شروع میشه، سیستم عامل یک Thread بهش اختصاص میده،

من بحثم رو ترد اصلی نیست رو تردی هست که باید برای پروسه checkbreak ایجاد بشه و اینکه وقتی A میخواد تردی را که به قولی درایور پروسه checkbreak هست اجرا کنه نیازی نیست خودش جزئی از همین ترد باشه.
وگرنه مطالبی که شما ارسال کردید همانی هست که باید گفته بشه همانطور که اینجا ارسال شد.
http://barnamenevis.org/forum/showpost.php?p=1111902&postcount=14.