Hirdetés

2024. május 2., csütörtök

Gyorskeresés

Hozzászólások

(#9301) Alexios válasza joysefke (#9300) üzenetére


Alexios
veterán

Gondolom az a probléma, hogy ez(legalábbis a leírása alapján) x86 vagy x64. Viszont netcore alatt a Microsoft.Data.Sqlite csomagnak is mennie kéne, és azzal szerintem lehet használni ef core-t arm-on is.

[ Szerkesztve ]

(#9302) joysefke válasza Keem1 (#9299) üzenetére


joysefke
veterán
LOGOUT blog

A Task-on már én is agyaltam, de amikor próbálkoztam, valahogy nem jött össze.

Tessék, ez így működik, gyakorlatilag semmit sem változtattam azon amit bemásoltál. (net framework 4.7.2 + ASP net core 2.1)

A Console.Readkey(). tartja életben a main thredet, az pedig közvetve a webservice-t. élesben nyilván a console.Readkey helyett valami olyan szerver metódusod lesz, ami sosem ér véget, ezáltal a backgroundban futó futó webservice is életben marad.

szerk (ne az IIS profillal futtasd)

    public class Program
    {
        static Task _webService;
        public static async Task Main(string[] args)
        {
            Debug.WriteLine("WebGUI Teszt");
            _webService = StartWebGui();
            Console.ReadKey();
        }

        static async Task StartWebGui()
        {
            var hostBuilder = new WebHostBuilder()
                    .UseKestrel()
                    .UseStartup<Startup>()
                    .UseUrls("http://localhost:808/")
                    .Build();
            await hostBuilder.RunAsync();
        }
    }

[ Szerkesztve ]

(#9303) Keem1 válasza joysefke (#9302) üzenetére


Keem1
addikt

Köszönöm. ezt kipróbálom :)

"élesben nyilván a console.Readkey helyett valami olyan szerver metódusod lesz, ami sosem ér véget, ezáltal a backgroundban futó futó webservice is életben marad"

Igen, ezt nagyon jól látod, a solution-ön belül két projectem van, a service, meg egy CLI verzió, próbálom mindkettőt életben tartani, mindkettőt tovább vinni. A CLI alapvetően teszteléshez, debuggoláshoz kell, amit bemásoltam, az onnan való, a service másképp működik.

Sematikusan:
---- Service (project)
---------- servicemethods.cs
---------- program.cs
---- CLI (project)
---------- program.cs (<--- servicemethods.cs)

Itt válnak ketté :)
Windows alatt a service-t lehet CLI-ként is futtatni, sajnos Linux alatt nem.
Ha Linux alatt futtatom, ezt kapom: Use mono-service to start service processes

Ezért fordítok egy második exe-t is, ami gyakorlatilag a paraméterek alapján hívogatja a fő class motyóit. A két program.cs pedig ezeket használja. Az egyik serviceként a másik pedig programként.

#region Service class
public class Service : ServiceBase
{
public Service()
{
ServiceName = Program.ServiceName;
}
protected override void OnStart(string[] args)
{
Program.OnStart(args);
}
protected override void OnStop()
{
Program.OnStop();
}
}
#endregion
#region Main method, application's entry point
/// <summary>
/// The main entry point for the application.
/// </summary>
static void Main(string[] args)
{
AppInfo.UseLocalDatabaseFolder = true;
if (System.Environment.UserInteractive)
{
ics.logger.Info("Run as application");
bool showMenu = true;
while (showMenu)
{
showMenu = ConsoleApp.MainMenu();
}
}
else
{
ics.logger.Info("Run as service");
using (var service = new Service())
{
ServiceBase.Run(service);
}
}
}
#endregion

(#9304) Keem1 válasza Alexios (#9301) üzenetére


Keem1
addikt

Köszönöm a tanácsot, de úgy néz ki, ez is elfailel, bár ez más miatt. :F

Már akkor elkezdtem ijedezni, mikor még Windows alatt is belebotlott a bicskája a connection stringben átadott "version" paraméterben, aminek eddig sem PHP, sem .NET 4.5, sem Java alatt nem volt baja :DDD

Ez az én kis teszt kódom SQLite teszteléshez:
using (SqliteConnection conn = new SqliteConnection($@"Data Source=F:\chinook.db;Version=3"))
{
        conn.Open();
        using (SqliteCommand cmd = new SqliteCommand("SELECT `name` FROM sqlite_master WHERE type='table';", conn))
        {
                SqliteDataReader reader = cmd.ExecuteReader();
                while (reader.Read())
                {
                        System.Console.WriteLine(reader.GetString(0));
                }
        }
}

És Linux alatt ezt kaptam:
Unhandled exception. Microsoft.Data.Sqlite.SqliteException (0x80004005): SQLite Error 14: 'unable to open database file'.
at Microsoft.Data.Sqlite.SqliteException.ThrowExceptionForRC(Int32 rc, sqlite3 db)
at Microsoft.Data.Sqlite.SqliteConnection.Open()
at Program.Main(String[] args) in ...\Program.cs:line 24

[ Szerkesztve ]

(#9305) martonx válasza Keem1 (#9299) üzenetére


martonx
veterán

Ne mondd már: https://www.nuget.org/packages/Microsoft.Data.Sqlite.Core/3.1.8
Talán 2-3 évvel ezelőtt ez igaz is lehetett, manapság ami nincs .Net Core-hoz, azzal nem is érdemes foglalkozni.

Én kérek elnézést!

(#9306) martonx válasza Keem1 (#9304) üzenetére


martonx
veterán

Gyors Guglizás után a version keyword nem támogatott Microsoft.Data.Sqlite.Core alatt függetlenül az operációs rendszertől, más kérdés, hogy Linux alatt szerintem eleve helytelen útvonal az F:\chinook.db
Helyette Mode=ReadOnly kell a connectionstringbe?

https://entityframeworkcore.com/knowledge-base/53662829/-net-core-ef6-fehler-mit-sqlite-verbindungszeichenfolge

Én kérek elnézést!

(#9307) Keem1 válasza martonx (#9306) üzenetére


Keem1
addikt

Nem, Linuxon nem ezt a path-t használtam :)
Viszont megvan a hiba, nem a Microsoft.Data.Sqlite.Core kell, hanem a Microsoft.Data.Sqlite. Úgy műxik.
Vannak névkonvencióbeli eltérések a hivatalos verzió és a Microsoft sajátja között, azt már észrevettem. Na de ez a hülyeség, hogy nem mondhatom meg, hogy a DB-m milyen verziójú, ez nonszensz :D

De úgy tűnik, ezzel tényleg működik ARM alatt.

No offense, de ha már itt tartunk. Mi az a fő indoka annak, hogy a(z elvileg még maintained) .Net xxx használata eretnekségnek minősül, és ami nincs Core alatt, az felejtős? Tehát mi az az ok, ami miatt a Core mindenképp használandó, más meg kerülendő?
Én úgy tudtam, az adott programnyelv, környezet csak egy eszköz, semmiképp sem határozza meg a végtermék minőségét. Akár lyukkártyával is megoldhatnám az adott feladatot - más kérdés, hogy meg tudom-e :DDD

Igen, tudom, a Core eleve opensource-nak, végre platformfüggetlennek készült (más kérdés, hogy eredetileg a .Net is, a Java babérjaira akart törni a 2000-es évek elején), de miért gáz jelenleg .Net-et használni helyette, ha egyébként tökéletesen működik és fejlesztik is?

[ Szerkesztve ]

(#9308) Alexios válasza Keem1 (#9307) üzenetére


Alexios
veterán

A .NET fw 4.8-al véget ért, security patchek érkeznek hozzá egy darabig, és kész. Idén jön a .NET 5, az már a core-ra épül, ez a jövő
Inkább pont fordítva, mi értelme .net fw-ben egy új projektet kezdeni?(főleg 4.5-ben)

Ráadásul ha linuxon is akarsz .net-et futtatni, eleve nem látom értelmét mással kezdeni, mint az ott natívan támogatott .net core-al

[ Szerkesztve ]

(#9309) Keem1 válasza Alexios (#9308) üzenetére


Keem1
addikt

Sajnos igazad van :(
Azt hittem, párhuzamos lesz a kettő, de itt is mást írnak.

All future investment in .NET will be in .NET Core,” says Microsoft. “.NET Framework 4.8 will be the last major version of .NET Framework.”

[ Szerkesztve ]

(#9310) joysefke válasza Keem1 (#9307) üzenetére


joysefke
veterán
LOGOUT blog

Mi az a fő indoka annak, hogy a(z elvileg még maintained) .Net xxx használata eretnekségnek minősül, és ami nincs Core alatt, az felejtős? Tehát mi az az ok, ami miatt a Core mindenképp használandó, más meg kerülendő?

Én inkább úgy fogalmaznék, hogy ha valami 3rd party packaget használsz, akkor ha az nincsen .Net Standard-re (lehetőleg max 2.0-ig) akkor az felejtős. Ha van, akkor az jó, mert egy esetleges net framework => net core át-targetelésnek nem fog útjában állni.

Én semmilyen körülmények között nem használnék olyan 3rd party libet ahol nem látom azt, hogy az arra épülő kódomat át tudom változtatás nélkül emelni akkor is ha futtatókörnyezetet váltok alatta. (lépek frameworkről 4.X-ről Core-ra)

Ezzel párhuzamosan ha kódot írok próbálom úgy szervezni, hogy közvetlenül framework 4.x-et targetelő projekt(ekbe) minél kevesebb kerüljön és inkább átcsoportosítom olyan projektekbe amelyek netstandard2.0-át targetelnek.

(#9311) martonx válasza Keem1 (#9307) üzenetére


martonx
veterán

Látom a többiek időközben megválaszolták a jövő vs. miért ne ragadjunk a múltban, hiszen kényelmes kérdésedet.

Én kérek elnézést!

(#9312) Keem1


Keem1
addikt

Ok meggyőztetek. Viszont elakadtam, még egy egyszerű tutorial se megy. Windowson oké, Linuxon nem. Mutatom, légyszi segítsetek. :R

Úgy néz ki, hogy a kis projektem minden egyéb eleme megy Linuxon is, csak a service nem működik. Amúgy tök jó ötlet volt megszabadulni 41 warningtól (unused variable) meg kikukáztam pár, már sehol nem használt metódust is :DDD
Valahogy ezt a nyamvadt service-t kéne megszülni. Az átoperálás után Windowson az eredeti service .Net Core 3.1-en is megy, és megy az alábbi példa is. Linuxon egyik se.
Ja, és console appként Linuxon is kiválóan megy, az SQLite is :C
Csak a service nem... :U

[link]

Eredmény Linuxon ( .Net Core 3.1)
Unhandled exception. System.PlatformNotSupportedException: ServiceController enables manipulating and accessing Windows services and it is not applicable for other operating systems.
at System.ServiceProcess.ServiceBase..ctor()
at Testing.LoggingService..ctor()
at Testing.Program.Main(String[] args) in E:\..\Program.cs:line 39
Félbeszakítva

[ Szerkesztve ]

(#9313) Alexios válasza Keem1 (#9312) üzenetére


Alexios
veterán

Hát, elég egyértelmű az exception :D
.NET Core 3-al bekerültek olyan api-k is, amik nem platformfüggetlenek. Pl. WPF kódot lehet .NET Core 3-al írni, de ettől még nem fogod tudni linuxon futtatni, ha tippelnem kéne akkor a System.ServiceProcess is ilyen

[link]
Szerintem ezt a linket nézd meg, itt jó eséllyel találsz megoldást

(#9314) Keem1 válasza Alexios (#9313) üzenetére


Keem1
addikt

Hát ez remek.. :((
Jó, akkor ezt egyelőre jegelem, nincs kedvem vacakolni egy olyan funkcióval, ami 4.5 alatt pár sor, .NET Core alatt meg egy csomó macera.
Majd ha lesz tengernyi időm, akkor szenvedek még vele.

Köszi azért...

(#9315) joysefke válasza Keem1 (#9312) üzenetére


joysefke
veterán
LOGOUT blog

.

[ Szerkesztve ]

(#9316) joysefke válasza Keem1 (#9314) üzenetére


joysefke
veterán
LOGOUT blog

Net api analyzer. Keress rá, rakd fel a VSre és futtasd le mindenféle net standard és net core targetekre, compatibility pack opcióval és anélkül.

Egyébként mit csináltál? Átraktad a target frameworkot 4.5 ről netcore 3.1 re és most futási időben kapsz hibát? Hogyan futtattad ezt eddig linuxon?

Amikor átállítottad a target frameworkot, akkor kellett compatibilitás csomagot feltenni?

[ Szerkesztve ]

(#9317) Keem1 válasza joysefke (#9316) üzenetére


Keem1
addikt

Nem, dehogyis, nyitottam a solution-ön belül egy teljesen új .Net Core 3.1-es projectet, a már létező .Net 4.5-ös console és az ugyancsak 4.5-ös service mellé.

A service pojecten belül még van 4 db class-em, amik a tényleges munkát végzik, úgy vannak megírva, hogy ne függjenek az adott projecttől (példa: Ac, Bc, Cc, Dc, ezek a class-ek más-más feladatot csinálnak). A service is és a console is ugyanezeket használja.
A console pl. nem tartalmaz mást, mint 4 db szöveges menüpontot, az 1, 2, 3 és 4 gomb lenyomására voltaképp a fenti class-ek [Ac|Bc|Cc|Dc].Run() nevű metódusát hívják meg és végrehajtják.
A service is voltaképp ugyanezt csinálja, csak időzítetten, mint egy crontab, megadott időben az Ac.Run(), Bc.Run(), stb hívogatódik, de emellett persze mást is: compactolja az SQLite-ot, futtatja a mini webservert, backupolja a MySQL és az SQLite db-ket.

Az eredeti elképzelés az volt, hogy a kettő egyben lenne (service-ként, amit a --console argumentummal lehet "menüsíteni"), Windows alatt simán működik is amúgy, alapvetően a --console arggal simán bedobja a console menüt, ketté is van választva a Main() (if (--console) RunConsole(); else RunService();), ez Windows alatt csodásan működik, de a Linux közli, hogy service programot csak service-ként lehet futtatni. Végül a Linux miatt készült egy pár soros Main()-ből álló console verzió is, aminek a tartalma a megírás óta nem változott (ahogy említettem, a menüt futtatja), de igazából a service Main()-je sem... hisz minden abban a 4 db class-ben módosul/frissül.

Tehát, összegezve... van egy 4 db classből álló feladatcsomagom, amik a Raspberry Pi-n különböző feladatokat hajtanak végre. Emellett van egy console app, ami mauálisan ezeket a feladatokat futtatja, Win/Linux egyaránt. Van egy service-m, ami szintén ezeket futtatgatja, de időzítve, plusz a webes elérést biztosító webserver, plusz pár backup és hasonlók, minden olyasmi, amit egy állandóan a háttérben mozgó service kell hogy futtasson.

[ Szerkesztve ]

(#9318) martonx válasza Keem1 (#9317) üzenetére


martonx
veterán

Szia, így kell .net core-t service-ként linuxon futtatni: https://swimburger.net/blog/dotnet/how-to-run-a-dotnet-core-console-app-as-a-service-using-systemd-on-linux

Én kérek elnézést!

(#9319) kiskornel


kiskornel
addikt

Sziasztok!
Adott egy függvényem, aminek az első bemenő paramétere int, viszont a 2. már lehet string, int, vagy objektum... a 3. 4. 5. paraméter szintúgy különböző típusok lehetnének.

Azt vágom, hogy kell később vizsgálni, hogy milyen típus, de hogy kell a függvény paramétereit leírni, hogy híváskor elfogadjon akár számot, akár stringet, akár objektumot?

Előre is köszi

http://www.flickr.com/photos/34330024@N05/sets/

(#9320) sztanozs válasza kiskornel (#9319) üzenetére


sztanozs
veterán

https://stackoverflow.com/questions/11046622/variant-type-in-c-sharp

JOGI NYILATKOZAT: A bejegyzéseim és hozzászólásaim a személyes véleményemet tükrözik; ezek nem tekinthetők a munkáltatóm hivatalos állásfoglalásának...

(#9321) fatal` válasza kiskornel (#9319) üzenetére


fatal`
titán

Attól függ mit szeretnél, C#-ban nincs union type. Ha csak kiírni ToString()-gel, akkor a #9320-ban említettek is megfelelőek lehetnek.

Lehet több overloadot csinálni (persze 5 paraméternél ez baromi sok lenne), vagy pedig builder patternre (vagy ahhoz hasonlóra) lehet szükséged, bár ez konstruktornál hasznos.

Akár típusra pattern matching is játszhat.

A cél nélkül nehéz megmondani :)

(#9322) petyus_ válasza kiskornel (#9319) üzenetére


petyus_
senior tag

Mutatnál példát könnyebb lenne.

Így bármennyi paramétert át tudsz adni:
Method(int x, params object[] obj){}

De nem tűnik túl tisztának így a kód, ha mutatsz belőle, lehet meg lehet csinálni jobban is.

(#9323) joysefke válasza kiskornel (#9319) üzenetére


joysefke
veterán
LOGOUT blog

szvsz:
-(A) vagy több overloadolt függvény dekalrációt használsz ugyanazzal a függvénynévvel, de különböző paramétertípusokkal , e.g.: void A (int, string, string); void A (int, object, object);
-(B) vagy egyszerűen object-ként deklarálod a különböző bemenő paramétereket és bent egy type-matching switch statementel eldöntöd a konkrét típust.

-(C) gondolom tisztában vagy a generikus típus/metódusdeklaráció mikéntjével és nem erre lenne igazából szükséged:
pld
public int Foo<T1,T2,T3>(int x, T1 p1, T2 p2, T3 p3){
           
    Console.WriteLine($"{p1.GetType()}  {p2.GetType()} {p3.GetType()}");
    return x;
}

(#9324) kiskornel válasza joysefke (#9323) üzenetére


kiskornel
addikt

Köszönöm a válaszokat. A cél egy log fájl írása lenne. Bárhol a progiban ahol Catch ágra fut, ott meg kellene hívnom egy errorlog függvényt, aminek az első paramétere, egy int (hol száll el) ... ez tiszta. DE...
A eset: a második paraméter meg mondjuk egy string (név) , harmadik egy int (ciklusszámláló).
B eset: a második paraméter egy WebClient (maga az objektum), harmadik param. egy webclient response (a válasz, amit ad), negyedik egy string (URL, ahonnan meg lett az hívva).
C eset: stb...

Tehát a paraméterek száma is változik (gondolom optional kell legyenek az elhagyható paraméterek) és még a típusuk is változik össze vissza. A függvény belülről nem gond, a típusazonosítás után már fel lehet dolgozni, de nem akarok tömböt definiálni, mikor hívom a függvényt, csak a paramétereket zárójelben bepakolni, átadni.

Az átadott paramétereket meg szétbontom, formázom, és kiírom a log fájlba.

Csak tanulás céljából kérdezem, mert túl sok macera, meg lehet kerülni, máshogy kivitelezni. (meg mert így szokták a nagyok).

Lenne kérdésem a válaszokkal kapcsolatban is, de ha felteszem, tutti elviszi a témát. :R

Még1x köszönöm a válaszokat, mindent átguglizok. :)

http://www.flickr.com/photos/34330024@N05/sets/

(#9325) sztanozs válasza kiskornel (#9324) üzenetére


sztanozs
veterán

Log fájlba az alábbi dolgok kellenek:
- esemény ideje (UTC vagy timezone megadásával)
- esemény szintje (amennyiben szükséges)
- esemény típusa (és/vagy azonosítója)
- esemény forrása (és vagy forrás azonosítója)
- esemény sikeressége (ha típus szinten ezt nem különítjük el)
- esemény üzenet

Tehát egy logoló kódba nem kell beledobálni mindenféle objektumokat. Azt vagy egy előre definiált esemény-objektummal kell feltölteni, vagy szöveges mezőket megadni.

[ Szerkesztve ]

JOGI NYILATKOZAT: A bejegyzéseim és hozzászólásaim a személyes véleményemet tükrözik; ezek nem tekinthetők a munkáltatóm hivatalos állásfoglalásának...

(#9326) joysefke válasza kiskornel (#9324) üzenetére


joysefke
veterán
LOGOUT blog

Vannak loggoló frameworkok, pld "Serilog". https://github.com/serilog/serilog/wiki/Getting-Started#example-application

Itt egy videó https://www.youtube.com/watch?v=ljZpWbuK68s

A loggolás pedig ennyi:

catch (Exception ex){
Log.Error(ex, "Something went wrong. Részletek: {param1} {param2} {param3}", param1, param2, param3);             
}

Ha nem teljesítmény kritikus az applikáció akkor a fenti séma jó is...

mindent átguglizok
abból semmit nem lehet tanúlni

[ Szerkesztve ]

(#9327) petyus_ válasza kiskornel (#9324) üzenetére


petyus_
senior tag

Ahogy a többiek is írták, a logger-be nem kéne ilyen logikát rakni, annak már csak azt az adatot kellene átadnod, ami a logba kerül.

"A függvény belülről nem gond, a típusazonosítás után már fel lehet dolgozni, de nem akarok tömböt definiálni, mikor hívom a függvényt, csak a paramétereket zárójelben bepakolni, átadni."

Ha mégis így akarod, akkor a params-t használd, ahogy korábban írtam:
Method(int x, params object[] obj){}
Itt nem kell létrehoznod semmilyen tömböt, vesszővel elválasztva pakolhatod be a paramétereket, utána a függvényen belül viszont a tömb elemein kell végigmenned.

[ Szerkesztve ]

(#9328) Keem1


Keem1
addikt

Ezt meg kell osszam veletek skacok :D Nem, nem száll a fejembe a dicsőség, 25 irtó könnyű kérdés, aki ezeket nem tudja szintén 100%-osra megválaszolni, az annyit jelent, hogy még tanulja/tanulnia kell a nyelvet. De azért örülök, hogy puskázás nélkül 25/25 lett :DDD

(#9329) joysefke válasza Keem1 (#9328) üzenetére


joysefke
veterán
LOGOUT blog

C# is an alias of C++. True, False? :D

(#9330) Keem1 válasza joysefke (#9329) üzenetére


Keem1
addikt

Azaz :DDD :C

(#9331) DrojDtroll


DrojDtroll
addikt

Sziasztok!

Van sok 8MB-os fájlom, amit szeretnék feldolgozni. A fájlok pontosan 2048x2048 db előjel nélküli két byte-os egész számot tartalmaznak binárisan.

Az első megoldásban két for ciklus segítségével olvastam be 16 bitenként. Próbaként megpróbáltam 64 bitet beolvasni és biteltolással előállítani a 64 bites számból a 4db 16 biteset. Úgy néz ki ez a módszer kb. kétszer olyan gyors mint a 16 bites.

Különböző tömböket kapok és nem tudom hol a hiba.

Mi okozza a különbséget?

Pastebin link

[ Szerkesztve ]

(#9332) joysefke válasza DrojDtroll (#9331) üzenetére


joysefke
veterán
LOGOUT blog

Nincs időm kipróbálni, de nekem egyáltalán nem szimpatikus egy ilyen nagy fájlnak a mini adagokban való szekvenciális olvasgatása.

1, Miért nem a sima stream Read metódussal olvasol azonnal byte[] tömbbe?
2, Én megpróbálnám a bufferméreteket manuálisan feljebb húzni. Alapból csak valami ici-pici bufferekkel dolgozik. (nekem pár 10KB rémlik)
3, Nem mintha itt számítania kellene de te itt ugye 4M elemen iterálsz át egy szoros for () ciklusban => ha nem fájlműveletet végeznél, akkor már ez is bizonyos helyzetekben indokolatlanul lassú (4M tömbhatár ellenőrzés az indexerekre+ ellenőrzés az iterátoron, szerk: mondjuk 4M az még nem túl sok..)
(4, miért int tömbben-ben tárolod a short értékeidet?)

5, a két kód ránézésre nem ugyanazt csinálja. a második konkrétan elcseszettnek tűnik.
64bitenként olvasol és ugyanúgy 4M-szor mint amikor 16 bitenként olvastál????

[ Szerkesztve ]

(#9333) joysefke válasza joysefke (#9332) üzenetére


joysefke
veterán
LOGOUT blog

Uhh az utolsó pontot visszavonom, látom, hogy a belső ciklus 4esével változik növeli a törzsön belül a ciklusváltozót. késő van na :B
Nyilván segít neki, hogy negyed annyi io van. De igazán jo szvsz akkor lesz ha nagy puffer mellett byte tömböt olvasol be addig amíg van mit olvasni.

[ Szerkesztve ]

(#9334) DrojDtroll válasza joysefke (#9332) üzenetére


DrojDtroll
addikt

Megvan mi volt a hiba forrása: nem úgy vannak tárolva az adatok ahogy azt elképzeltem.
Nem sorrendben vannak leírva a byte-ok hanem fordított sorrendben. Meg kell cserélni azt a két byte-ot ami a számot tárolja.

(#9335) joysefke válasza DrojDtroll (#9331) üzenetére


joysefke
veterán
LOGOUT blog

for (int i = 0; i < heigth; i++)
{
    for (int j = 0; j < width; j++)
    {
        result[j, i] = reader.ReadUInt16();
    }
}

Itt van még egy olyan probléma (mindkét példádban), hogy úgy iterálsz át egy nagy többdimenziós tömbön, hogy a belső ciklusod nem a tömb legjobboldalibb dimenzióján iterál.

C#-ban a többdimenziós tömbök (A[,,,]) row-major ként vannak a memóriában, tehát a legjobb oldalibb dimenzió egymás melletti elemei a memóriában egymás mellett lesznek. az A[100, 50] elem mellett az A[100,51] elem van. Ezzel szemben az A[101,50] az teljesen máshol van, a te esetedben (2048) elemmel később mint az A[100,50], tehát mivel int tömbről van szó, 8KB-tal később van. Az hogy itt csak írsz és nem olvasol kb mindegy, mert nyilván egy egész cache line lesz írva/olvasva.

A helyzeten cache-line szempontből még (valószínűleg) tovább ront itt, hogy kettő hatványonként iterálsz. ilyen problémák nagy mátrixok szorzásánál vannak

[ Szerkesztve ]

(#9336) joysefke válasza DrojDtroll (#9334) üzenetére


joysefke
veterán
LOGOUT blog

Igen, én is észrevettem, de szvsz nem a forrásadatokkal van a probléma, hanem a két metódusod nem ugyanazt a bytesorrendet használja, tehát a tömbök tartalma amelyeket visszaadnak sem ugyanaz lesz.

Amikor a második metódusban streamből beolvasol egy ulongot, akkor a ReadUInt64() figyelembe veszi az x86 bytesorrendjét: a változónak a kisebb helyiértékű byteja van alacsonyabb címen (little endian). Ha a streamed sorrendben ezeket a byteoket tartalmazza:
1, 0x01; 2, 0x02; 3; 0x03; 4, 0x04; 5; 0x05; 6, 0x06; 7, 0x07;8, 0x08;

akkor a kiolvasott ulong értéke az 0x08'07'06'05'04'03'02'01 lesz, szemben azzal a sorrenddel amit a fileban látsz.

Ha ezt a részt fordított sorrendbe raknád, akkor pont ugyanazt a tömböt adná vissza a kettő metódusod.

                        result[++j, i] = (ushort)(r >> 48);
                        result[++j, i] = (ushort)(r >> 32);
                        result[++j, i] = (ushort)(r >> 16);
                        result[++j, i] = (ushort)r;

[ Szerkesztve ]

(#9337) DrojDtroll válasza joysefke (#9335) üzenetére


DrojDtroll
addikt

Köszönöm a segítséget. A forráson nem tudok változtatni, ott van rossz más sorrendben az adat. A további feldolgozás a megszokott (legjobb oldalibb) indexelést használja. Az adatok későbbi feldolgozása miatt van szükség az int-ben való tárolásra.

(#9338) joysefke válasza DrojDtroll (#9337) üzenetére


joysefke
veterán
LOGOUT blog

        public static int[,] Get4mIntArrBufferedSpan(string fileName)
        {
            var sw = new Stopwatch();
            uint heigth = 2048;
            uint width = heigth;
            var result = new int[heigth, width];
            var buffSize = sizeof(ushort) * heigth;
            var buff = new byte[buffSize];
            using (var fs = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.None, bufferSize: 1024 * 1024))
            {
                sw.Start();
                for (int w = 0; w < width; w++)
                {
                    int chunk = 0;
                    while (chunk < buffSize)
                        chunk += fs.Read(buff, chunk, (int)buffSize - chunk);
                    
                  var shortArr = MemoryMarshal.Cast<byte, ushort>(buff);
                    for (int h = 0; h < heigth; h++)
                      result[h, w] = shortArr[h];
                }
                sw.Stop();
                Console.WriteLine($"{nameof(Get4mIntArrBufferedSpan)} took {sw.ElapsedMilliseconds}ms");
            }
            return result;
        }

Nekem a fenti kód pontosan ugyanazt az eredmény tömböt dobja ki mint a te első metódusod. A különbség annyi, hogy a itt while ciklus megpróbál egyszerre 4096byteot (2048db ushort) kiolvasni a streamből, a kiolvasott byte tömböt castolja ushort-tömbre azzal pedig feltölti egy oszlopodat.

Szóval itt is rossz a tömb bejárási sorrendje, de a Stream.Read() metódus úgy tűnik, hogy ennyivel hatékonyabb, mint egyenként ushortokat olvasgatni. (nálam pontosan duplázódott a sebesség)

A fenti kódban ha a mátrix bejárási sorrendje "normalizálódna" akkor további 3x lenne gyorsabb. ==> tehát igen, itt a processzor fogja vissza a fájlműveletet :)

Ebben az esetben lenne értelme egyszerre 2048db elemnél többet is olvasni. Az még dobna rajta.

[ Szerkesztve ]

(#9339) Keem1


Keem1
addikt

Srácok, Linq segítséget kérnék.

Ez így az objektumot adja vissza:
System.Net.Dns.GetHostEntry(System.Net.Dns.GetHostName()).AddressList.Where(ip => ip.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork).Select(ip => ip.ToString()).ToList();

Addig jó, hogy ha lehagyom a végéről a selectet, akkor ugye az eredmény List<IpAddress>, viszont nekem List<string> kellene, de nem az ojjektum nevéről :DDD :R

(#9340) joysefke válasza Keem1 (#9339) üzenetére


joysefke
veterán
LOGOUT blog

???

Az eredmény egy List<string> ami stringként ábrázolt IP-címeket tartalmaz, hol itt a probléma?

(#9341) Keem1 válasza joysefke (#9340) üzenetére


Keem1
addikt

Hátöö.... nem.. :D
Nem az IP lesz stringként, hanem az object neve.

Szerk... ja de. :U Szóval próbálkoztam, megterveztem a kérdést, majd megírtam a jó megoldást és végül azt posztoltam ide? Ez történhetett? :DDD

Szóval megvan a megoldás, nincs kérdés, sorry! :B

[ Szerkesztve ]

(#9342) Tomi_78


Tomi_78
tag

Sziasztok!
Most kezdtem kóstolgatni a C# programozást, és ehhez egy kis grafikus programot írnék SharpDevelop környezetben. Viszont a programom futtatásakor azt írja ki, hogy:
"Az "egydenever" név nem szerepel ebben a környezetben"
illetve a DrawImage-ben a két utolsó paramétert (srcRect és units) nem ismeri, bár nem is tudom, hogy ide miket kéne megadni.
Tudnátok segíteni ennek a két hibajelenségnek a megoldásában? Íme a kódom:
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;

namespace Animacios
{
    /// <summary>
    /// Description of MainForm.
    /// </summary>
    
    public partial class MainForm : Form
    {    
        Bitmap deneverkepe1 = new Bitmap("kepei\\kisdenever1bmp.bmp");
        Bitmap deneverkepe2 = new Bitmap("kepei\\kisdenever2bmp.bmp");
        
        class Deneverek
        {
            public int dirx,diry,kepe;
        };
        
        public MainForm()
        {
            //
            // The InitializeComponent() call is required for Windows Forms designer support.
            //
            InitializeComponent();
            //
            // TODO: Add constructor code after the InitializeComponent() call.
            //
            deneverkepe1.MakeTransparent();
            deneverkepe2.MakeTransparent();
            
            Deneverek[] egydenever = new Deneverek[3];
            int svsz;
            for (int i=0; i<3; i++) {
                egydenever[i]= new Deneverek();
                System.Random vsz = new System.Random();
                svsz = vsz.Next(1);
                if (svsz==0) {
                    egydenever[i].dirx = -1;
                } else {
                    egydenever[i].dirx = 1;
                };
                svsz = vsz.Next(1);
                if (svsz==0) {
                    egydenever[i].diry = -1;
                } else {
                    egydenever[i].diry = 1;
                };
                svsz = vsz.Next(1);
                if (svsz==0) {
                    egydenever[i].kepe = 0;
                } else {
                    egydenever[i].kepe = 1;
                };
            };
        }
        void AnimIdozitoTick(object sender, EventArgs e)
        {
            for (int i=0; i<3; i++) {
                if (egydenever[i].kepe==0) {
                    egydenever[i].kepe=1;
                }
                else {
                    egydenever[i].kepe=0;
                };
            };
        }
        void MozgIdozitoTick(object sender, EventArgs e)
        {
            for (int i=0; i<3; i++) {
                switch (egydenever[i].dirx) {
                    case -1:
                        if (egydenever[i].Left>0) {
                            egydenever[i].Left-=4;
                        }
                        else egydenever[i].dirx*=-1;
                    break;
                    case 1:
                        if (egydenever[i].Left<800-egydenever[i].Width) {
                            egydenever[i].Left+=4;
                        }
                        else egydenever[i].dirx*=-1;
                    break;
                };
                switch (egydenever[i].diry) {
                    case -1:
                        if (egydenever[i].Top>0) {
                            egydenever[i].Top-=4;
                        }
                        else egydenever[i].diry*=-1;
                    break;
                    case 1:
                        if (egydenever[i].Top<600-egydenever[i].Height) {
                            egydenever[i].Top+=4;
                        }
                        else egydenever[i].diry*=-1;
                    break;
                };
            };
        }
        void MainFormPaint(object sender, PaintEventArgs e)
        {
            for (int i=0; i<3; i++) {
                if (egydenever[i].kepe==0) {
                    e.Graphics.DrawImage(deneverkepe1,egydenever[i].Left,egydenever[i].Top,srcRect, units);
                }
                else {
                    e.Graphics.DrawImage(deneverkepe2,egydenever[i].Left,egydenever[i].Top,srcRect, units);
                }
            }
        }
    }
}

(#9343) Alexios válasza Tomi_78 (#9342) üzenetére


Alexios
veterán

Szia,

Nem teljesen értem a kódodat, ezt valahonnan kimásoltad? A problémák amik előjöttek azért vannak, mert olyan változókat használsz amik nincsenek sehol deklarálva.
Pl. az srcRect és units változókat miért adtad meg a DrawImage-ben, ha nincsenek is ilyenjeid?

Az egydenever változót használod minden metódusban, pedig a konstruktorban, mint lokális változó hozod létre. Ha egy metóduson belül hozol létre egy változót, akkor az csak azon a metóduson belül fog élni, máshol nem, ezt javíthatod a kódon belül pl. így:
Bitmap deneverkepe1 = new Bitmap("kepei\\kisdenever1bmp.bmp");
Bitmap deneverkepe2 = new Bitmap("kepei\\kisdenever2bmp.bmp");
Deneverek[] egydenever;

majd később már csak ehhez rendelsz értéket:
egydenever = new Deneverek[3];
int svsz;

De érdemes lenne első körben a nyelv alapjait is átnézned.

Illetve miért pont SharpDevelop, ami évek óta discontinued állapotban van?

[ Szerkesztve ]

(#9344) martonx válasza Tomi_78 (#9342) üzenetére


martonx
veterán

Miért SharpDevelop?

Én kérek elnézést!

(#9345) Tomi_78 válasza Alexios (#9343) üzenetére


Tomi_78
tag

Szia Alexios!

Köszönöm a választ; ezzel egyúttal azt a kérdésemet is megválaszoltad, hogy kezdőérték nélküli, dinamikus tömböt hogyan lehet létrehozni. :K
Még javítottam a kódomon annyit, hogy a képe egy változóba kerüljön, tehát:
class Deneverek
        {
            public int dirx,diry;
            public Bitmap kepe;
       };                      

(...)
if (svsz==0) {
                    egydenever[i].kepe = deneverkepe1;
                } else {
                    egydenever[i].kepe = deneverkepe2;
                };

De ezek után pl. a kirajzolásban nem ismeri fel a képhez tartozó Left és Top változókat:
void MainFormPaint(object sender, PaintEventArgs e)
        {
            for (int i=0; i<3; i++) {
                    e.Graphics.DrawImage(egydenever[i].kepe,egydenever[i].kepe.Left,egydenever[i].kepe.Top,egydenever[i].kepe.Width,egydenever[i].kepe.Height);
            }
        }

Ez miért van?
És hogy miért pont SharpDevelop? Martonxnek is válaszolva: már régebben a gépemen pihen letöltve és csak most vettem elő. Az tetszett benne annakidején, hogy ingyenes és kicsi: csak letöltöd, kitömöríted és használatra kész. Nem tudom, van-e még ilyen fejlesztőkörnyezet, de nekem egyelőre bejön. :K Azt viszont én is sajnálom, hogy már nem fejlesztik tovább a készítői.

(#9346) Tomi_78


Tomi_78
tag

Bocs, az előbb javítottam és láttam, hogy nem kezdőérték nélküli a Deneverek tömb... Így javítottam a programomon, de most csak egy denevér jelenik meg, az sem animálódik és nem is mozog:
namespace Animacios
{    
    public partial class MainForm : Form
    {    
        Bitmap deneverkepe1 = new Bitmap("kepei\\kisdenever1bmp.bmp");
        Bitmap deneverkepe2 = new Bitmap("kepei\\kisdenever2bmp.bmp");
        
        class Deneverek
        {
            public int dirx,diry,xhely,yhely;
            public Bitmap kepe;
        };
        
        Deneverek[] egydenever;
        
        public MainForm()
        {
            //
            // The InitializeComponent() call is required for Windows Forms designer support.
            //
            InitializeComponent();
            //
            // TODO: Add constructor code after the InitializeComponent() call.
            //
            deneverkepe1.MakeTransparent();
            deneverkepe2.MakeTransparent();
            
            egydenever = new Deneverek[3];
            int svsz;
            for (int i=0; i<3; i++) {
                egydenever[i]= new Deneverek();
                System.Random vsz = new System.Random();
                svsz = vsz.Next(1);
                if (svsz==0) {
                    egydenever[i].dirx = -1;
                } else {
                    egydenever[i].dirx = 1;
                };
                svsz = vsz.Next(1);
                if (svsz==0) {
                    egydenever[i].diry = -1;
                } else {
                    egydenever[i].diry = 1;
                };
                svsz = vsz.Next(1);
                if (svsz==0) {
                    egydenever[i].kepe = deneverkepe1;
                } else {
                    egydenever[i].kepe = deneverkepe2;
                };
                egydenever[i].xhely=vsz.Next(1,800-egydenever[i].kepe.Width);
                egydenever[i].yhely=vsz.Next(1,600-egydenever[i].kepe.Height);
            };
        }
        void AnimIdozitoTick(object sender, EventArgs e)
        {
            for (int i=0; i<3; i++) {
                if (egydenever[i].kepe==deneverkepe1) {
                    egydenever[i].kepe=deneverkepe2;
                }
                else {
                    egydenever[i].kepe=deneverkepe1;
                };
            };
        }
        void MozgIdozitoTick(object sender, EventArgs e)
        {
            for (int i=0; i<3; i++) {
                switch (egydenever[i].dirx) {
                    case -1:
                        if (egydenever[i].xhely>0) {
                            egydenever[i].xhely-=4;
                        }
                        else egydenever[i].dirx*=-1;
                    break;
                    case 1:
                        if (egydenever[i].xhely<800-egydenever[i].kepe.Width) {
                            egydenever[i].xhely+=4;
                        }
                        else egydenever[i].dirx*=-1;
                    break;
                };
                switch (egydenever[i].diry) {
                    case -1:
                        if (egydenever[i].yhely>0) {
                            egydenever[i].yhely-=4;
                        }
                        else egydenever[i].diry*=-1;
                    break;
                    case 1:
                        if (egydenever[i].yhely<600-egydenever[i].kepe.Height) {
                            egydenever[i].yhely+=4;
                        }
                        else egydenever[i].diry*=-1;
                    break;
                };
            };
        }
        void MainFormPaint(object sender, PaintEventArgs e)
        {
            for (int i=0; i<3; i++) {
                    e.Graphics.DrawImage(egydenever[i].kepe,egydenever[i].xhely,egydenever[i].yhely,egydenever[i].kepe.Width,egydenever[i].kepe.Height);
            }
        }
    }
}

(#9347) Tomi_78 válasza Tomi_78 (#9346) üzenetére


Tomi_78
tag

Na végre, minden működik, kivéve hogy a képek villognak egy kissé. Ezt nem lehet valahogy kiküszöbölni? Az Invalidate(); függvény ennyire akadozna?

(#9348) Keem1 válasza Tomi_78 (#9342) üzenetére


Keem1
addikt

Ahogy látom, nem csak C#, hanem úgy általában objektumorientált programozási alapok is csiszolásra szorulnak. Én nem vagyok tanár, és a topik témája is bőven kimerül a tanításban, de én a következőket javasolnám neked:

- rengeteg jó forrás van (leginkább angol nyelven), mégis egy egyszerű, könnyen tanulható és magyar nyelvű könyvet javasolnék: Sipos Marianna: Programozás élesben - C# (megadja a kezdő löketet, az abszolút alapokat)
- kezdésnek én WinForms helyett console-ban gyakorolnék, alapoznék. Ha ez flottul megy, akkor jöhet az ablakozás. Az ablakozás mindaddig várhat, míg a nyelv alapjait meg nem ismered: keywordök, objektumok, névterek, metódusok, láthatóság, öröklődés, stb.

Tényleg csupa jó tanácsként szánom a fentieket, és elnézést, ha tévedtem, rosszul mértem fel, hogy nem csak C#-ban, de úgy alapból OO programozásban is abszolút kezdő vagy.
Amúgy meg a C# szerintem egy szuper nyelv: egyszerű, könnyen kezelhető, de mégis sokoldalú. Főleg a rengeteg forrásanyag, tutorial, 3rd party libraryk miatt.

(#9349) Tomi_78 válasza Keem1 (#9348) üzenetére


Tomi_78
tag

Utánanézek a könyvnek, bár nekem is vannak programozással (C++ és C# is) foglalkozó köteteim, igaz, végigolvasni még egyet sem volt időm vagy türelmem. Inkább célirányosan kutatok, ha szembesülök valami problémával, mert azt már nem kell nekem elmagyarázni, hogy mi a tömb, az elágazás vagy a ciklus, hanem inkább az olyan dolgokat, amik az adott fejlesztőkörnyezet sajátosságai, mint pl. hogy C#-ban hol kell elhelyezni a globális változókat a kódban vagy hogy bizonyos deklarálásokat milyen formában kell megadni.
Lehet, hogy velem van a hiba, hogy szájbarágósan és nem bikkfanyelven várom el a szakkönyvektől is a magyarázatokat, dehát ez van.
Az OOP lényegét is úgy mondanám el, hogy tagolva vannak benne a dolgok, az események csak azok szükségessége esetén hajtódnak végre, és nem folyamatosan, ciklikusan figyeli a program az összes tennivalót.

(#9350) disy68 válasza Tomi_78 (#9349) üzenetére


disy68
aktív tag

"Az OOP lényegét is úgy mondanám el, hogy tagolva vannak benne a dolgok, az események csak azok szükségessége esetén hajtódnak végre, és nem folyamatosan, ciklikusan figyeli a program az összes tennivalót."

Hmm. Az egymondatos definíció mindig nehéz, de azért az események nem igazán tartoznak ide.

OOP alapelvek:
- Absztrakció
- Polimorfizmus
- Öröklődés
- Egységbezárás

“Yeah, well, you know, that’s just, like, your opinion, man.” — The Dude

Copyright © 2000-2024 PROHARDVER Informatikai Kft.