Asagidaki gibi program parcamiz olsun.
function F1():boolean
begin
if x=1 then halt;
end;
function F2():boolean
begin
...........
...........
F1();
...........
...........
end;
procedure Tform1.P1click(sender:Tobject);
begin
F2();
.........
.........
.........
end;
Eger X=1 olursa program durur.
Boyle degilde F1 fonksiyonunda X=1 olursa Form1 de baslatilmis tum fonksiyon yada procedurlerden cikilsin istiyorum.
Bunu basitse
function F1():boolean
begin
result:=true;
if x=1 then exit;
result:=false;
end;
function F2():boolean
begin
result:=true;
...........
if F1() then exit;
...........
...........
result:=false;
end;
procedure Tform1.P1click(sender:Tobject);
begin
if F2() then exit;
.........
.........
.........
end;
Seklinde yapabiliriz.
Boyle yapmak yerine ilk program parcacigindaki Halt yerine yazilacak bir komutla yapamazmiyim?
Tum islemleri durdurup Form1 in en yalin hic bir islemin baslatilmadigi duruma donmemi saglayan bir komutumuz varmi?
Selamlar kolay gelsin,
bahsettiğiniz şekilde tek bir komut olduğunu sanmıyorum, ben hiç görmedim.
Bunu yapmaktaki amacınız nedir ?
Herhangi bir anda ornegin elektrik kesildi bilgisi gelirse o anki tum islemler terkedilsin ve ana forma donulsun.
Elektrik kesildiginde sistem o an icin icinden cikilmasi cok zaman alacak fonksiyonlari isletiyor olabilir. O fonskiyonun icinde de elektrik
kesildimi flagini zirt pirt kontrol etmek istemiyorum.
Elektrik kesilince program nasıl çalışacak ?
pc ups ile pc nin kontrol ettiği sistem ise çalışmayacak (çalıştığım yerde bu tip makinalar var oradan aklıma geldi)
Bu tıp durumlar için pratik bir yol yokmu?
Diyelimki 100 tane fonksiyon yazdınız. Her biri bir önceki fonskiyonu çağırıyor.
En baştaki fonksiyonu çağırdınız, o onu o onu derken 100. fonksiyona geldiniz.
Bu aşamada öyle bir durum oluştuki artık fonskiyonlardan gerisin geriye dönmenin anlamı yok. Sanki program yeni çalıştırılmış gibi en
başa dönmek hatta ana forma gelmek istiyorum.
Halt deyip programı yeniden başlattırmak çözüm ama yakışıklı değil. Yazılmış bir programın her satırına da hata kontrolu ekleyip hata
varsa fonskiyonu terket demek de işime gelmiyor açıkcası.
Tümünü bir thread içine yerleştirirsin. Mesela Thread 10 dakikalık bir iş yapıyor olsun. Bunu daha 3. dakikada sonlandırmak istersen dışarıdan başka bir thread tarafından veya formun kendisinden TerminateThread(.. fonksiyonu ile sonlandırırsın. Aşağıdaki gibi sınırsız döngü veya başka bir iş yapıyor bile olsa sonlandırabilirsin. while true do
begin sleep(1) end;
http://www.google.com.tr/search?hl=tr&safe=off&q=%22TerminateThread%22+%22delphi%22&meta=&aq=f&aqi=&aql=&oq=&gs_rfai=
Java olsa bir exception oluştururdum, öyle bir exception olurdu ki bu iç içe olan fonksiyonlardan kaçmasına izin verirdim, en yukarı kadar giderdi. 100. fonksiyonu da atlattıktan sonra yakalar, gereğini yapardım.
Sanırım Delphi'de de exception kavramı var. Benzer bir yöntem izlenebilir.
o kadar fonksiyonu iç içe yazmak zorunda mısınız ? daha basit bi tasarım yapsanız bu kadar uğraşmazsınız.
delphi için fonksiyonu bildirdik işte yolu yöntemi budur bunla yapılır.
http://www.google.com.tr/search?hl=tr&safe=off&q=%22TerminateThread%22+%22delphi%22&meta=&aq=f&aqi=&aql=&oq=&gs_rfai=
Hatta başka bir program ile de sonlandırabilirsiniz. Thread işe başlamadan önce IDsini bir yere gönderir yayın yapar yada dosyaya yazar. Bunu bilen her hangi bir program onu sonlandırabilir.
100 tane fonksiyon çağıran programın amacı nedir? daha kolay bi yol bulunabileceğine eminim.
t2,
Bunlar dolambaçlı yöntemler. Exception yöntemi ise tam da bu tür işler için idealdir. Hataların sınıflandırılmasını, istenilen yerde istenilen şekilde çözülmelerini ve programın her yerinde "if" kullanmadan kontrol edilebilmelerini sağlar. "Hata" dediğim şey gerçek anlamda bir hata olmayıp kullanıcının oluşturduğu bir durum da olabilir.
orhanc,
bunalmis sadece örnek vermiş. 100 değil de 5 tane olsun, mantık aynı. Sayı az diye her fonksiyonun içine bir boolean değişken koyup kontrol etmek doğru olmaz. Belki iş görür ama iyi bir programcının yapacağı şey değil, özellikle de exception desteği veren yüksek seviye bir dil ile uğraşılıyorsa.
Abartılı örneklerin sorunun anlaşılması açısından, basit kaçamak cevapların gelmemesi açısından verildiğini anlayın lütfen.
Exeption kullanın denmiş fakat,
100 tane fonskiyonum olsa herbirine tek tek exeption ilave etmem gerekmeyecekmi?
sorunu söylersen ona göre cevap vermek daha kolay olur.
Alıntı yapılan: Tagli - 09 Nisan 2010, 11:52:41
t2,
Bunlar dolambaçlı yöntemler. Exception yöntemi ise tam da bu tür işler için idealdir. Hataların sınıflandırılmasını, istenilen yerde istenilen şekilde çözülmelerini ve programın her yerinde "if" kullanmadan kontrol edilebilmelerini sağlar. "Hata" dediğim şey gerçek anlamda bir hata olmayıp kullanıcının oluşturduğu bir durum da olabilir.
orhanc,
bunalmis sadece örnek vermiş. 100 değil de 5 tane olsun, mantık aynı. Sayı az diye her fonksiyonun içine bir boolean değişken koyup kontrol etmek doğru olmaz. Belki iş görür ama iyi bir programcının yapacağı şey değil, özellikle de exception desteği veren yüksek seviye bir dil ile uğraşılıyorsa.
Aynı değil işte. Her soruna değişik çözümler bulunabilir.
Bu yazıyı bir incelemenizi tavsiye ederim.
http://en.wikipedia.org/wiki/Spaghetti_code (http://en.wikipedia.org/wiki/Spaghetti_code)
Ben PIC programlamaya yeni başladım ve görüyorum ki pic programcılarının çoğu çok gereksiz ve uzun kodlar yazıyorlar. Biz web veya windows programcılığında en kısa haliyle işi çözmek için uğraşırız.
Alıntı yapılan: bunalmis - 09 Nisan 2010, 11:56:36100 tane fonskiyonum olsa herbirine tek tek exeption ilave etmem gerekmeyecekmi?
Hayır. Bir fonksiyonda exception oluşursa ve içerde çözümlenemezse, oluştuğu fonksiyonu sonlandırarak bunu çağıran bir üst fonksiyona gider (benim deyimimle "kaçar"). Herhangi bir "catch" bloğunda yakalanmadığı sürece yukarı doğru kaçmaya devam eder ve yolu üzerindeki fonksiyonları da sonlandırır. En sonunda kendini yakalayabilecek bir "catch" bloğuna denk geldiğinde, o bloktaki işlemler yapılır. Exception'lar da birer nesnedir. Oluşturulduğu yerde içlerine bilgiler yüklenebilir, bu bilgilere yakalandıkları yerde erişilebilir. Ayrıca sınıflandırılabilirler. Bunu, Java için konuşmak gerekirse, Exception class'ını extend ederek kendimiz bir class oluşturarak yaparız. "catch" bloklarını da kendi oluşturduğumuz bu class'ı (yani exception'u) yakalayacak şekilde ayarlayabilirz.
Delphi'deki exception'ların Java'dakilerden ne kadar farklı olduklarını bilmiyorum. Delphi'de exception olduğunu da zaten 10 dakika önce Google'da yazınca öğrendim.
Birbirini çağırmış 100 tane fonksiyon 100 katlı bina ve 100. Fonksiyon "Çatı" ise, Halt komutu çatıya çıkanın "aşağı atlaması" olur.
Eğer sub rutini çağırmışsanız bir üste dönmeniz şarttır.
Birinci sebebi stack yönetimi ilk giren ilk çıkar kaidesiyle yönetilir.
İkincisi sistem sizin üst rutinlerde yarattığınız nesnelerin sonlandırma bilgisine ihtiyaç duyar ve bu bilgi rutin sonlandırıldığında ortaya çıkar bu sayede çöp toplayıcı bellekten artık kullanmadığınız alanları temizler.
Assembly ile stack yığınındaki dönüş adresi değiştirilebilir ancak yığın sayısı azaltılamaz. 100 rutin çağırmışsanız 99 tanesi stackde kalır. Bu durumda bir müddet sonra stack owerflow hatasının fırlatılmasına sebep olur.
Sub1(Kosul)
if Kosul=Dogru then Sub2(Dogru)
End Sub1
Sub2
if Kosul=Dogru then Sub3
End Sub2
Sub3
if PortXXX=H17 then Sub4
End Sub3
Sub4
if MemoryXXX<>H717234 then Sub5
End Sub4
Sub5
try
if Handle=DogruDeger then
return
else
SubXXX
end if
catch ex as exception
hatayı işle
end try
End Sub5
Stack yığını yukardaki yapı benzeri iç içe geçmiş 1000 alt rutin çağrısından oluşsa bile;
Top stacke geri dönmeyi gerektirecek en alt rutinden itibaren kod akışı hiç bir şeyi etkilemeyecek bir hızda roota döner. (çağrı yapan üst rutinlerde dönüş aşamasındada bir işlem yoksa)
Dönüş aşamasındada bir işlem varsa zaten oradaki işlemin yapılması gerekeceğinden Top stacke direk dönmek çözüm olamaz.
Hata yakalama için kullanılan Exception sınıfı hiç bir şekilde stack yığınını boşaltmaz. Kod akışını try-catch bloğu içinde hatanın oluştuğu satırdan sonraki kodların işletilmeden catch satırına yönlendirilmesini sağlar. Yani bir üst rutine dönüşte exception sınıfının hiç bir etkisi yoktur. try blokları sadece programın kırılmasını engeller. Programın Trust olarak tanımlanabilmesi için her kritik kod için kullanılması zorunludur ve hatta kritik kodlar öncesinde "ben şu dizindeki şu dosyayı yazmak için açacağım, müsade edermisin ?", "Ben regde şunu değiştirecem" vs. diye sistemden izin alınması tavsiye edilir :)
Mikroişlemci üzerinde kod yazıyor olsaydım örnek sorudaki gibi dallanıp budaklanıp programın ucra noktalarından bir yere gelmiş olsaydım ve herseye ilk kez başlıyormuşum durumuna dönmek isteseydim reset vektörüne uçmam yeterliydi yada Stack registeri stagın başına çekip ana rutine zıplayabilirdim.
(Tabi interrupları geçici süre için askıya alırdım. Bunlar teferruat kısmı.)
Burada ise windows gibi el dikiyle bir şeyler yapmaya çalışıyoruz.
Alıntı yapılan: Tagli - 09 Nisan 2010, 12:06:36
Alıntı yapılan: bunalmis - 09 Nisan 2010, 11:56:36100 tane fonskiyonum olsa herbirine tek tek exeption ilave etmem gerekmeyecekmi?
Hayır. Bir fonksiyonda exception oluşursa ve içerde çözümlenemezse, oluştuğu fonksiyonu sonlandırarak bunu çağıran bir üst fonksiyona gider (benim deyimimle "kaçar"). Herhangi bir "catch" bloğunda yakalanmadığı sürece yukarı doğru kaçmaya devam eder ve yolu üzerindeki fonksiyonları da sonlandırır. En sonunda kendini yakalayabilecek bir "catch" bloğuna denk geldiğinde, o bloktaki işlemler yapılır. Exception'lar da birer nesnedir. Oluşturulduğu yerde içlerine bilgiler yüklenebilir, bu bilgilere yakalandıkları yerde erişilebilir. Ayrıca sınıflandırılabilirler. Bunu, Java için konuşmak gerekirse, Exception class'ını extend ederek kendimiz bir class oluşturarak yaparız. "catch" bloklarını da kendi oluşturduğumuz bu class'ı (yani exception'u) yakalayacak şekilde ayarlayabilirz.
Delphide Try Exception var. Bunları 1/0, strtoint gibi hata üretme ihtimali olan kodların hata durumunda özel işlemler yapmada kullanıyorum.
Fakat Try exception ı sorumdaki duruma nasıl uyarlayacağımı anlayamadım.
Delphi'deki exception'ların Java'dakilerden ne kadar farklı olduklarını bilmiyorum. Delphi'de exception olduğunu da zaten 10 dakika önce Google'da yazınca öğrendim.
İşletim sistemlerinede hak vermek lazım,
1,2,3 bilemedin 4 tane işlemciyle binlerce process kontrol et, milyarlarca bit arasında git gel, bide bunlar yetmiyomuş gibi orana burana mikrofon, hoporlör jakı, usb konnektörü soksunlar,
"dünyanın en mutlu, en zengin, en sağlıklı adamı olcan, 500 senede ömür verecez deseler" windowsun arkada uğraştıklarıyla uğraşmam :)
hasangurlek, senin koda döktüğün yapı benim anlatmaya çalıştığımdan farklı olmuş. Ben "catch" bloğunun en derinde değil en üstte olmasından bahsetmiştim, yani sub1'de. sub5'te sadece "throw new Exception();" benzeri bir satır olacak, sub2, 3, 4 ve 5'te "catch" bloğu olmayınca exception 1'e kadar kaçıp sub1'deki catch'e yakalanacak. Bu durumda sub2, 3, 4 ve 5'in sonlanması gerekir, stack'te de adresleri kalmaz diye biliyorum.
Aradığınız komut EXIT olabilir mi?
unit Unit4;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls,qdialogs;
type
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
h,t,z:integer;
sbit:boolean;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
begin
h:=0;
sbit:=false;
while h < 1000 do
begin
t:=0;
h:=h+1;
canvas.TextOut(0,0,inttostr(h));
application.ProcessMessages;
while t < 1000 do
begin
z:=0;
t:=t+1;
canvas.TextOut(0,20,inttostr(t));
application.ProcessMessages;
while z < 1000 do
begin
z:=z+1;
canvas.TextOut(0,40,inttostr(z));
application.ProcessMessages;
if sbit = true then exit;
end;
end;
end;
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
application.MessageBox('Program sonlandı','EXIT Ornegi',0);
sbit := true;
end;
end.
Düzeltme: İstediğiniz şeyin , farklı fonksiyonları aynı anda sonlandırmak olduğunu, mesajı yazdıktan sonra farkettim.
Alıntı yapılan: Tagli - 09 Nisan 2010, 12:29:29
hasangurlek, senin koda döktüğün yapı benim anlatmaya çalıştığımdan farklı olmuş. Ben "catch" bloğunun en derinde değil en üstte olmasından bahsetmiştim, yani sub1'de. sub5'te sadece "throw new Exception();" benzeri bir satır olacak, sub2, 3, 4 ve 5'te "catch" bloğu olmayınca exception 1'e kadar kaçıp sub1'deki catch'e yakalanacak. Bu durumda sub2, 3, 4 ve 5'in sonlanması gerekir, stack'te de adresleri kalmaz diye biliyorum.
Evet sizin yazdığınızda bir yöntem ama try-catch bloğu arasındaki her birim kod izlemeye alındığı için önemli derecede kaynak israfına sebep olur. Bunun için kritik kodların blok içine alınması daha doğrudur. Bu blok ilk rutinde olduğunda alttaki tüm kod hata izlemek üzere takibe alınır. Farklılıkları dosyanın varlığı, okuması vs. hakkında koda dökersek ;
Private Sub FileProcesses()
Try
FileReadProcess("C:\test.txt")
Catch ex As Exception
MessageBox.Show("Dosya hatası")
End Try
End Sub
Private Sub FileReadProcess(ByVal FileName As String)
Dim FS As FileStream = New FileStream(FileName, FileMode.Open, FileAccess.Read, FileShare.Read)
Dim SR As StreamReader = New StreamReader(FS, Encoding.UTF8)
Dim Str As String = SR.Read()
SR.Close()
FS.Close()
End SubBu kod daha performanslı koşacak durumda;
Private Sub FileProcesses()
If FileReadProcess("C:\test.txt") Then
'İŞLEMLER
End If
End Sub
Private Function FileReadProcess(ByVal FileName As String) As Boolean
Dim FS As FileStream = Nothing
Try
FS = New FileStream(FileName, FileMode.Open, FileAccess.Read, FileShare.Read)
Catch ex As Exception
MessageBox.Show("Dosya okuma hatası")
Return False
End Try
Dim SR As StreamReader = New StreamReader(FS, Encoding.UTF8)
Dim Str As String = SR.Read()
SR.Close()
FS.Close()
Return True
End FunctionBu çok daha hızlı koşacaktır;
Private Sub FileProcesses()
If File.Exists("C:\test.txt") Then
FileReadProcess("C:\test.txt")
'İŞLEMLER
Else
MessageBox.Show("Dosya bulunamadı")
End If
End Sub
Private Sub FileReadProcess(ByVal FileName As String)
Dim FS As FileStream = New FileStream(FileName, FileMode.Open, FileAccess.Read, FileShare.Read)
Dim SR As StreamReader = New StreamReader(FS, Encoding.UTF8)
Dim Str As String = SR.Read()
SR.Close()
FS.Close()
End SubMicrosoft amcanın tavsiye ettiği;
Private Sub FileProcesses(ByVal ReadOrWrite As Boolean, ByVal FileName As String)
If ReadOrWrite Then
If FileReadProcess(FileName) Then
'ISLEMLER
End If
Else
'YAZMA
End If
End Sub
Private Function FileReadProcess(ByVal FileName As String) As Boolean
If File.Exists(FileName) Then
Dim Permission As New System.Security.Permissions.FileIOPermission( _
System.Security.Permissions.FileIOPermissionAccess.Read, FileName)
Try
Permission.Demand()
Try
Dim FS As FileStream = New FileStream(FileName, FileMode.Open, FileAccess.Read, FileShare.Read)
Dim SR As StreamReader = New StreamReader(FS, Encoding.UTF8)
Dim Str As String = SR.Read()
SR.Close()
FS.Close()
Return True
Catch ex As Exception
MessageBox.Show("Dosya okuma hatası")
End Try
Catch ex As Exception
MessageBox.Show("Kullanıcı yetkiniz dosya okuma işlemi için yeterli değil")
End Try
Else
MessageBox.Show("Dosya bulunamadı")
End If
Return False
End FunctionEn sondaki tavsiyeye uyuyormusun diye bana sorarsanız özellikle son 2 aydır sistemden izin almak dahil evet. Herhangi bir makinede hiç ummadık bir zamanda programın kırıldığına şahit olmuşluğum çok fazla. Vatandaş girmiş internete okumuş birşeyler ve hemen öğrendiklerini uygulamış sonra arıyor ;
Alıntı Yap
Şikayet : Program açılmıyor, bu ne yahu kullanamayacakmıyız biz bunu !
Soru : Programa tıklayınca hata mesajı vermedenmi kapanıyor ?
Kullanıcı: evet, hiçbişi yapmıyo
Soru : Şu klasöre bak, şu dosya duruyormu ?
Kullanıcı: (10 dakka sonra) Evet, burda
işi gücü bırakıp gidip bakıyorsun
Soru : Dosya izinleri ile kim oynadı ?
Kullanıcı : Virüs bozmasın diye biz yaptık !
İyide kardeşim veri dosyalarının, konfigürasyon dosyalarının izinlerini iptal edersen program nasıl okucek, yazcek ?
Cevap : Biz sandıkki şey, eeee
Bülent hocam affola, delphi arenasını basice döndürdüm, hakkını helal et.
Programını Yönetici olarak çalıştırırsan öyle bir sorunun oluşmaması gerekiyor.