PDA

View Full Version : سوال: خطای دلفی !



تجلی
شنبه 03 دی 1390, 19:12 عصر
سلام .
در زیر دو نوع کد میارم که در هر دو بلوک خطا وجود داره اما خیلی جالبه که در اولی ، بعد از ارجاع خطا به بخشexcept ، خط بعد از خطا هم اجرا میشه ولی در دومی ، دستور بعد از خطا اجرا نمیشه و فقط except اجرا میشه .
کد اول اینه >
در این کد دستور بعد از خطا یعنی فعال شدن مجدد تایمر اتفاق میافته >( خطا در حالتی رخ میده که چیزی از جانب سرور برای خوانده شدن توسط کلاینت ارسال نشده )



procedure TForm1.Timer1Timer(Sender: TObject);
begin
try
timer1.Enabled:=false;
memo1.Lines.Add(idtcpclient1.IOHandler.ReadLn());
timer1.Enabled:=true;
except

end;
end;



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



procedure TForm1.Timer1Timer(Sender: TObject);
var a:Extended;
begin
try
timer1.Enabled:=false;
a:=3/StrToInt(edit2.Text);
timer1.Enabled:=true;
except

end;
end;



حالا سوال اینجاست : من هیچ جا ندیدم اشاره ای به نوع خطا در دلفی شده باشه اما به نظر میرسه بلوک مدیریت خطای بالا در مورد بعضی خطاها متفاوت عمل میکنه . به نظر شما تفاوت دو نوع خطای بالا در چیه و چرا دلفی بین اونها تفاوت قائل میشه ؟

vcldeveloper
شنبه 03 دی 1390, 19:53 عصر
Exception ایی که در کد اول دریافت می کنید، دقیقا چی هست؟ آیا در داخل دیباگر فقط نمایش داده میشه، یا اینکه خارج از دیباگر هم نمایش داده میشه؟

در کد اول از Indy استفاده کردید که از Exception ها به عنوان یک مکانیزم کنترلی در داخل خودش استفاده میکنه. بعضی از این Exception ها برای Indy معنی دارند، ولی خارج از دیباگر اصلا به کد شما نمی رسند، و توسط Indy هندل میشند. در ضمن، نوشتن بلوک های try - except بدون مشخص کردن نوع Exception مورد نظر، و بدون نوشتن کدی برای هندل کردن Exception بوجود اومده، کار اشتباهی هست. وقتی هم که با Indy کار می کنید، اهمیت این اشتباه بیشتر هم میشه، چون خفه کردن Exception به این شکل روی روند کنترلی Indy میتونه تاثیر بذاره.

تجلی
شنبه 03 دی 1390, 20:24 عصر
متشکر از پاسختون .
اگر کد اول رو در بلوک قرار ندم چه در دیباگر باشه و چه خارج از اون با هر بار اجرای تایمر با خطای زیر مواجه میشم >

access violation at adrress 004E4E7 in module...read of address ...

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

جدای از موضوع بالا یه مشکلی دیگه ای هم دارم : اینه که در کد اول اگر این تایمر به طور پیشفرض غیر فعال باشه و بخوام بعد از کانکت شدن به سرور با یه دکمه تایمر رو فعال کنم برنامه هنگ میکنه ! ولی اگر قبل از کانکت شدن به سرور فعالش کرده باشم هنگ نمیکنه . این مشکل از چیه ؟ آیا یک باگه یا اینکه من دارم جایی اشتباه میکنم ؟

اول فکر کردم شاید باید یه آنتی فریز روی فرم بزارم اما چیزی عوض نشد . و متاسفانه اون تاپیکی که توش درباره آنتی فریز صحبت شده رو هم پیداش نکردم که ببینم اصلا ربطی داره یا نه .

vcldeveloper
یک شنبه 04 دی 1390, 15:50 عصر
اگر کد اول رو در بلوک قرار ندم چه در دیباگر باشه و چه خارج از اون با هر بار اجرای تایمر با خطای زیر مواجه میشم
خب Access Violation خطای مهمی هست، و نباید هرگز اون رو با استفاده از try - except بدون مدیریت کردنش، خفه کنید. اگر در سورس خودتون Access Violation دریافت می کنید، باید حتما اون رو بررسی و برطرف کنید. Access Violation میتونه منجر به خراب شدن فضای حافظه در دسترس برنامه شما بشه، و اگر هم در این بخش از کد برنامه تون خفه اش کنید، در جای دیگه ایی از برنامه که به داده های اون بخش خراب شده از حافظه میخواید دسترسی پیدا کنید، به مشکل بر خواهید خورد. البته از اونجایی که Access Violation را اینجا خفه کردید، معلوم نمیشه که کجا به مشکل بر می خورید، و این مشکل ممکنه در نقاط مختلف برنامه تون به شکل های مختلف رخ بده، و شما هم هیچ سرنخی از این رفتار عجیب و غریب برنامه تون نداشته باشید. درباره Access Violation، علت های پیدایش آن، و راهکارهایی برای پیدا کردن عامل اصلی بروز این خطا، در همین سایت و در اینترنت اطلاعات متنوعی وجود داره.


جدای از موضوع بالا یه مشکلی دیگه ای هم دارم : اینه که در کد اول اگر این تایمر به طور پیشفرض غیر فعال باشه و بخوام بعد از کانکت شدن به سرور با یه دکمه تایمر رو فعال کنم برنامه هنگ میکنه ! ولی اگر قبل از کانکت شدن به سرور فعالش کرده باشم هنگ نمیکنه . این مشکل از چیه ؟ آیا یک باگه یا اینکه من دارم جایی اشتباه میکنم ؟
Indy به صورت blocking عمل میکنه، یعنی انجام هر عملیات در Indy تا زمان دریافت نتیجه عملیات، منجر به بلوکه شدن Thread شروع کننده اون عملیات میشه. پس اگر شما قبل از فعال کردن اون تایمر، کد مربوط به Connect شدن را اجرا کنید، تا زمانی که عملیات Connect شدن با موفقیت به اتمام نرسه، دستورات بعد از آن اجرا نخواهند شد. از طرف دیگه با توجه به اینکه شما دارید کد Connect را در داخل Thread اصلی برنامه اجرا می کنید، سایر فعالیت های این Thread هم تا پایان عملیات Connect دچار اخلال میشند، از جمله پردازش پیام های ویندوز، و آپدیت کردن رابط گرافیکی کاربر. عملیات های اینچنینی که منجر به بلوکه شدن یک Thread میشند را بهتر هست که در یک Thread مستقل انجام بدید، تا Thread اصلی برنامه تون بتونه به کار عادی خودش ادامه بده.