PDA

View Full Version : مشکل فراخوانی زیاد و خطای stack overflow exeption



Mahdi.21267
دوشنبه 25 اردیبهشت 1402, 08:58 صبح
سلام
متأسفانه در کدنویسی مجبورم داخل یک فرم بیش از چند هزار خط فراخوانی از فرم دیگر رو داشته باشم که باعث خطای stack overflow exeption میشه، وقتی تعداد خط های فراخوانی رو کم میکنم خطا برطرف میشه، لطفا راهنمایی کنید چه راه دیگه ای وجود داره که فراخوانی فرم دیگه انجام بشه ولی خطای stack نیاد.
تشکر

پرستو پارسایی
دوشنبه 25 اردیبهشت 1402, 16:12 عصر
به نظر من این مشکل احتمالا به دلیل ایجاد حلقه‌های بازگشتی در کد شما است که باعث ایجاد خطای stack overflow exeption می‌شوند. برای رفع احتمالی این مشکل :
1- استفاده از حلقه‌های بازگشتی با شرط خروج از حلقه
2- استفاده از توابع دستوری به جای حلقه‌های بازگشتی
3- محدود کردن تعداد فراخوانی‌ها با استفاده از شرط‌ های مناسب
4- بهینه سازی کدهای تکراری و استفاده از توابع کم حجم و با قابلیت استفاده مجدد
این موارد نظرات شخصی من هست ولی اساتید قطعا راه کارهای بهتری ارائه می دهند .

Private Sub RecursiveFunction(ByVal n As Integer, ByVal maxDepth As Integer, ByVal currentDepth As Integer)
If n > 0 AndAlso currentDepth <= maxDepth Then
RecursiveFunction(n - 1, maxDepth, currentDepth + 1)
Console.WriteLine(n)
End If
End Sub

در این کد، تابع RecursiveFunction با سه پارامتر ورودی تعریف شده است. پارامتر اول : n در کد فوق مشخص می‌کند که از چه عددی شروع به چاپ کردن اعداد به صورت نزولی (یک تا n ) کنیم . به عبارت دیگر، این پارامتر تعداد اعدادی را که می‌خواهیم چاپ کنیم تعیین می‌کند.
پارامتر دوم : (maxDepth) در کد فوق مشخص می‌کند که چه تعداد حداکثر فراخوانی از تابع مجاز است. به عبارت دیگر، این پارامتر تعداد حداکثر را مشخص می‌کند تا از خطای stack overflow exeption جلوگیری کنیم
پارامتر سوم : (currentDepth) در کد فوق تعداد فراخوانی‌های فعلی تابع RecursiveFunction را نگه می دارد .این پارامتر در شرط بستن حلقه استفاده می‌شود تا از خطای stack overflow exeption جلوگیری کنیم
در این حلقه اگر عدد به 1000 برسد حلقه بسته میشود

برای فراخوانی این تابع، می‌توانید به صورت زیر عمل کنید

RecursiveFunction(10, 1000, 0)

Mahdi.21267
دوشنبه 25 اردیبهشت 1402, 22:21 عصر
به نظر من این مشکل احتمالا به دلیل ایجاد حلقه‌های بازگشتی در کد شما است که باعث ایجاد خطای stack overflow exeption می‌شوند. برای رفع احتمالی این مشکل :
1- استفاده از حلقه‌های بازگشتی با شرط خروج از حلقه
2- استفاده از توابع دستوری به جای حلقه‌های بازگشتی
3- محدود کردن تعداد فراخوانی‌ها با استفاده از شرط‌ های مناسب
4- بهینه سازی کدهای تکراری و استفاده از توابع کم حجم و با قابلیت استفاده مجدد
این موارد نظرات شخصی من هست ولی اساتید قطعا راه کارهای بهتری ارائه می دهند .

Private Sub RecursiveFunction(ByVal n As Integer, ByVal maxDepth As Integer, ByVal currentDepth As Integer)
If n > 0 AndAlso currentDepth <= maxDepth Then
RecursiveFunction(n - 1, maxDepth, currentDepth + 1)
Console.WriteLine(n)
End If
End Sub

در این کد، تابع RecursiveFunction با سه پارامتر ورودی تعریف شده است. پارامتر اول : n در کد فوق مشخص می‌کند که از چه عددی شروع به چاپ کردن اعداد به صورت نزولی (یک تا n ) کنیم . به عبارت دیگر، این پارامتر تعداد اعدادی را که می‌خواهیم چاپ کنیم تعیین می‌کند.
پارامتر دوم : (maxDepth) در کد فوق مشخص می‌کند که چه تعداد حداکثر فراخوانی از تابع مجاز است. به عبارت دیگر، این پارامتر تعداد حداکثر را مشخص می‌کند تا از خطای stack overflow exeption جلوگیری کنیم
پارامتر سوم : (currentDepth) در کد فوق تعداد فراخوانی‌های فعلی تابع RecursiveFunction را نگه می دارد .این پارامتر در شرط بستن حلقه استفاده می‌شود تا از خطای stack overflow exeption جلوگیری کنیم
در این حلقه اگر عدد به 1000 برسد حلقه بسته میشود

برای فراخوانی این تابع، می‌توانید به صورت زیر عمل کنید

RecursiveFunction(10, 1000, 0)

سلام، ممنون از وقتی که گذاشتید و جواب دادید، کد من خیلی محاسباتی نیست که نیاز باشه به این صورت عمل بشه، فقط یسری اعمال گرافیکی(تغییر رنگ خطوط و ایمیج باکس و....) هست، راه حلی هست که دستور بدم از یه فرم دیگه ،مثلا خط 30 تا 250 اجرا بشه، دیگه نیاز نباشه اون حدود 220 خط رو یکی یکی وارد کد (فراخوانی) کنم.
مثلا تو حالت عادی برای فراخوانی مینویسم form260.line55.forecolor=color.red و از این فراخوانی ها چند هزار خط با شروط مختلف استفاده شده‌. ممنون از شما

پرستو پارسایی
سه شنبه 26 اردیبهشت 1402, 10:54 صبح
در این مثال، تابع ApplyChanges تمام تغییرات گرافیکی را انجام می‌دهد و سپس با مقدار عمق بعدی فراخوانی می‌شود. در هر بار فراخوانی، مقدار عمق چک می‌شود و اگر بیشتر یا مساوی حداکثر عمق مجاز بود، تابع متوقف می‌شود. در غیر این صورت، تغییرات گرافیکی اعمال می‌شود و تابع با مقدار عمق بعدی فراخوانی می‌شود.

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


Private Sub ApplyChanges(ByVal depth As Integer)
If depth >= MAX_DEPTH Then
Return
End If

' اعمال تغییرات گرافیکی
form260.line55.ForeColor = Color.Red
'...

' فراخوانی تابع با مقدار عمق بعدی
ApplyChanges(depth + 1)
End Sub


Private Const MAX_DEPTH As Integer = 10


Private Sub Button1_Click(ByVal sender As Object, ByVal e As EventArgs)
' شروع اجرای تابع با عمق اولیه ۰
ApplyChanges(0)
End Sub