Jump to content

Lūdzu palīdziet ar ātrdarbības problēmu manā programmā


dobbleextra
 Share

Recommended Posts

Sveiki!

Mans C#.NET kods darbojas pārāk lēni!

private void a(object sender, KeyPressEventArgs e)
        {
            if (e.KeyChar == 'd')
            {
                pictureBox1.Location = new Point(pictureBox1.Location.X + 10, 103);
                System.Threading.Thread.Sleep(50);
            }
            else if (e.KeyChar == 'a')
            {
                pictureBox1.Location = new Point(pictureBox1.Location.X - 10, 103);
                System.Threading.Thread.Sleep(50);
            }
        }

Problēma ir sekojoša : uz eventa ir divi if steitmenti un divi Sleep(50) tādēļ objeks, kuram ir jāpārvietojas uz priekšu kļūst gļukains, bet, ja izņemu ārā vai nu vienu vienu if vai nu vienu Sleep(50), tad viss darbojas. Pats netieku gudrs kā atrisināt šo problēmu. Varbūt kāds zina labāku veidu kā apturēt programmu?

Labots - dobbleextra
Link to comment
Share on other sites

Sleep() izmantot nav īsti laba doma - tikmēr visa Tava programma ir iesalusi un nevar neko darīt. Piemēram, pārzīmēties arī nevar, un visu ko citu, ko programmai jādara, arī nevar. Tizli.

 

Tā vietā vajag izmantot Timer kontroli. Timeris darīs tā, ka X reizes sekundē (cik nu bieži uzstādīsi) izpildīs Tick eventu.

 

Patiesībā, nevis X reizes, bet ne vairāk kā X reizes. Ja kompis būs ļoti noslogots, var arī izpildīties retāk. Bet biežāk noteikti nebūs. Tāpēc jāseko pašam līdzi, cik ilgs laiks pagājis. To dara tā, ka uztaisa vienu klases mainīgo, kurā pieraksta šobrīdējo laiku (DateTime.Now), un tad nākamajā reizē paskatās, cik daudz laika pagājis, un atkal uzstāda šo mainīgo uz šobrīdējo laiku.

 

Priekš normālas animācijas, ieteiktu kādas 20 reizes sekundē. Vari paeksperimentēt. Tur laikam bija aizture jānorāda milisekundēs - tātad, 50ms pauzes starp eventiem.

 

Tālāk dari tā - savā KeyPress eventā (starp citu, vienmēr sauc lietas normālos nosaukumos, nevis pliku "a"!) uzstādi vienu savas klases mainīgo. Teiksim "Speed". Tajā mainīgajā ieraksti, piemēram, "-10", ja jākustas pa kreisi; "+10", ja jākustas pa labi; un "0", ja nav jākustas vispār.

 

Tālāk, savā Timer.Tick eventā skaties, cik laiks pagājis, un skaties, kāda ir kustības mainīgā vērtība. Tālāk parēķini - pagājušas ir N sekundes (visdrīzāk kaut kāda daļa sekundes); un 1 sekundē Tu gribi pakustēties par "Speed" vienībām uz vienu vai otru pusi. Tad nu pavisam vienkārši - pictureBox.Location.x = pictureBox.Location.x + Speed*N;

 

Šādā veidā, vienalga, cik bieži izpildīsies Tick events, kamēr poga būs nospiesta, kastīte kustēsies ar fiksētu ātrumu 10 pixeļi/sekundē.

  • Patīk 2
Link to comment
Share on other sites

dobbleextra

Paldies, Vilks, domu sapratu un tiešām aizmirsu, ka, ja uzlikšu Sleep() programma arī nezīmēs uz ekrāna vairs. Taču nesapratu kur īsti jāliek tas timer1.start()? Iekš KeyPress? Tad lai tas taimeris darbojas tik ilgi līdz es atlaižu pogu?

 

 

 

 

Tā vietā vajag izmantot Timer kontroli. Timeris darīs tā, ka X reizes sekundē (cik nu bieži uzstādīsi) izpildīs Tick eventu.

Un starpcitu par to "a" es tā parasti nedaru tikai tagad es to notiekti izdarīju nepareizajā vietā pie eventiem ierakstot nepareizo lietu(tagad izlabošu).

Labots - dobbleextra
Link to comment
Share on other sites

Nē, nē. Tas taimeris ir komponente, kuru uzvelk uz formas, tāpat kā pogas un textboxus. Tam arī turpat nnorādi Enabled=True, un miers. Lai jau viņš tur raustās fonā visu laiku - kamēr Speed būs 0, tāpat nekas nenotiks.

 

Var jau čakarēties un slēgt iekšā uz KeyDown, un ārā uz KeyUp... bet tas ir baigais čakars, un jāseko līdzi, kad nospiež vairāk par vienu pogu, utt... Un ieguvuma nekāda.

Link to comment
Share on other sites

un katru reizi taisīt new Point(... arī nav labi. Pārāk daudz atmiņa tiek čakarēta.

Labots - gathis
Link to comment
Share on other sites

dobbleextra

Jā' bet .x nevar tā vienkārši mainīt.

Tomēr var jau 'protams'darīt tā:

Point punkts = objekts.Location.X

Objekts.Location = punkts

Bet vai tas ir tā vērts nezinu. A vispār cik liels ir viens Point?

Link to comment
Share on other sites

Wrong idea, gathis. .NET ar atmiņu ir citādāk, nekā C++. Šis ir pareizais veids, un tur nebūs nedz atmiņas čakarēšanas, nedz memory leak.

 

Alternatīvi šajā gadījumā var arī pietikt vienkārši ar .Left propertijas mainīšanu, lai nav jāčakarējas ar to Point.

Labots - Vilx-
Link to comment
Share on other sites

dobbleextra

Pld,nezināju. Taču, kā tad darbojas tā sistēma? Man arī likās, ir takā c++. Tāpēc jau man visu laiku likās dīvaini, ka nav delete!

Link to comment
Share on other sites

Pie neliela objekta skaita šādi protams, ka viss darbojas ok un GC darbojas labi.

Tomēr no pieredzes, jo lielāki apjomi, GC tomēr netiek smuki galā ar atmiņas atbrīvošanu un ir labāk pašam padomāt par to :)

Link to comment
Share on other sites

A kā pats par to padomāsi? Atmiņu pašam atbrīvot nav iespējams.

 

Par to, kā strādā GC ir gari raksti. Šai pieejai ir gan labās, gan sliktās puses. Teorija ir, ka vidusmēra programmā dažādu iemeslu dēļ šī pieeja ir efektīvāka nekā C++ pieeja, kur atmiņu jāatbrīvo pašam.

 

Bet ir iespējams arī uztaisīt tādu programmu, kas "iet pret spalvu", un rezultāts nav tik foršs. Taču tās jau ir smalkas tēmas. :)

 

Enīvei, šajā gadījumā tas pat nav aktuāli, jo "Point" ir struct, nevis class, un tur atmiņa nemaz netiek ņemta vai atbrīvota. :)

 

Pievenots:

 

OK, tagad ir mazliet vairāk laika rakstīt plašāk.

 

.NET, atšķirībā no C++, priekš atmiņas izmanto tehnoloģiju, ko sauc par "Garbage Collector". Lai arī tur apakšā ir ļoti sarežģīti algoritmi, vienkāršos vārdos, ir tā, ka Tev pašam atmiņu nemaz nevajag atbrīvot (aļa "delete" iekš C++). Tā vietā .NET pats seko līdzi visiem objektiem, un kuram objektam uz kuru ir atsauces. Laiku pa laikam viņš izskrien cauri visiem objektiem un sameklē tos, kuriem vairs nevar tikt klāt. Šos objektus .NET tad arī pats automātiski atbrīvo.

 

Kā jau teicu, tam ir dažādas spožās un ēnas puses, un C++ izstrādātāji ar .NET izstrādātājiem par to ir reliģijas kariņš jau vairāk kā 10 gadus. Ieteiktu par to daudz nedomāt. :)

 

Viens blakusefekts gan ir, ka rezultātā .NET objektiem nav tādu "destruktoru". Nu, faktiski ir, bet to izmantošana traucē GC (Garbage Collector) darbam, un Tu arī nevari pateikt, kad tas izpildīsies. Varbūt tagad, bet varbūt pēc 10 gadiem. :p

 

Vietās, kur tomēr ir nepieciešama kontrolēta objekta "iznīcināšana", ir uztaisīts sintakses triks - .NET ir definēts interfeiss "IDisposable", kuram ir viena metode "Dispose". C# valodā ir konstrukcija ar "using", kuru var pielietot objektem, kas šo interfeisu implementē:

using (var x = new File())
{
    // izmantojam x
}
Kad kodu nokompilēs, tas tiks pārveidots par:

var x = new File();
try
{
    // izmantojam x
}
finally
{
    x.Dispose();
}
Tas, protams, objektu "neiznīcina" un tā atmiņu neatbrīvo, bet visādu satīrīšanās loģiku gan tā var taisīt. Ja kaut kad sanāk izmantot objektus, kas implementē IDisposable, tad ir silti ieteicams tos lietot ar "using", lai vienmēr būtu drošs, ka obekts pareizi "aizveras". Labots - Vilx-
Link to comment
Share on other sites

Izveido kontu, vai pieraksties esošajā, lai komentētu

Jums ir jābūt šī foruma biedram, lai varētu komentēt tēmas

Izveidot jaunu kontu

Piereģistrējies un izveido jaunu kontu, tas būs viegli!

Reģistrēt jaunu kontu

Pierakstīties

Jums jau ir konts? Pierakstieties tajā šeit!

Pierakstīties tagad!
 Share

×
×
  • Izveidot jaunu...