- LordAthis: AI Kérdés érkezett - 3600 soros Spagetti kód refaktorálása és budget
- Luck Dragon: Asszociációs játék. :)
- sziku69: Fűzzük össze a szavakat :)
- Elektromos rásegítésű kerékpárok
- eBay-es kütyük kis pénzért
- Tutti Georg: A Microsoft 2025. augusztusi biztonsági frissítései hibásak
- D1Rect: Nagy "hülyétkapokazapróktól" topik
- GoodSpeed: Bye PET Palack, hello SodaStream
- sziku69: Szólánc.
- sh4d0w: Netflix? Ugyan, VW előfizetés!
Új hozzászólás Aktív témák
-
pmonitor
aktív tag
Te nem érted. Designer file-ra nincs is szükség. Ha akarod, akkor van, ha nem, akkor nincs.
Ezért írtam, hogy tudni kell, hogy mit csinál az ember fia/lánya.amikor legközelebb megnyitod a formot felül fogja írni.
Csak a megnyitásnál nem írja felül, csak ha módosítod is Designer nézetben. De akkor ugyebár direkt csináltad..
-
pmonitor
aktív tag
válasz
pmonitor #9497 üzenetére
Talán 4 perc is volt... Ezért írtam, hogy tudni kell, hogy mit csinál az ember fia/lánya.
using System;
using System.ComponentModel;
using System.Windows.Forms;
using System.Security.Permissions;
[PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
public class Form1 : Form
{
private IContainer components;
private WebBrowser webBrowser1;
private MenuStrip menuStrip1;
private ToolStripMenuItem fileToolStripMenuItem,
saveAsToolStripMenuItem, printToolStripMenuItem,
printPreviewToolStripMenuItem, exitToolStripMenuItem,
pageSetupToolStripMenuItem, propertiesToolStripMenuItem;
private ToolStripSeparator toolStripSeparator1, toolStripSeparator2;
private ToolStrip toolStrip1, toolStrip2;
private ToolStripTextBox toolStripTextBox1;
private ToolStripButton goButton, backButton,
forwardButton, stopButton, refreshButton,
homeButton, searchButton, printButton;
private StatusStrip statusStrip1;
private ToolStripStatusLabel toolStripStatusLabel1;
public Form1()
{
// Create the form layout. If you are using Visual Studio,
// you can replace this code with code generated by the designer.
InitializeComponent();
// The following events are not visible in the designer, so
// you must associate them with their event-handlers in code.
webBrowser1.CanGoBackChanged +=
new EventHandler(webBrowser1_CanGoBackChanged);
webBrowser1.CanGoForwardChanged +=
new EventHandler(webBrowser1_CanGoForwardChanged);
webBrowser1.DocumentTitleChanged +=
new EventHandler(webBrowser1_DocumentTitleChanged);
webBrowser1.StatusTextChanged +=
new EventHandler(webBrowser1_StatusTextChanged);
// Load the user's home page.
webBrowser1.GoHome();
}
// Displays the Save dialog box.
private void saveAsToolStripMenuItem_Click(object sender, EventArgs e)
{
webBrowser1.ShowSaveAsDialog();
}
// Displays the Page Setup dialog box.
private void pageSetupToolStripMenuItem_Click(object sender, EventArgs e)
{
webBrowser1.ShowPageSetupDialog();
}
// Displays the Print dialog box.
private void printToolStripMenuItem_Click(object sender, EventArgs e)
{
webBrowser1.ShowPrintDialog();
}
// Displays the Print Preview dialog box.
private void printPreviewToolStripMenuItem_Click(
object sender, EventArgs e)
{
webBrowser1.ShowPrintPreviewDialog();
}
// Displays the Properties dialog box.
private void propertiesToolStripMenuItem_Click(
object sender, EventArgs e)
{
webBrowser1.ShowPropertiesDialog();
}
// Selects all the text in the text box when the user clicks it.
private void toolStripTextBox1_Click(object sender, EventArgs e)
{
toolStripTextBox1.SelectAll();
}
// Navigates to the URL in the address box when
// the ENTER key is pressed while the ToolStripTextBox has focus.
private void toolStripTextBox1_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter)
{
Navigate(toolStripTextBox1.Text);
}
}
// Navigates to the URL in the address box when
// the Go button is clicked.
private void goButton_Click(object sender, EventArgs e)
{
Navigate(toolStripTextBox1.Text);
}
// Navigates to the given URL if it is valid.
private void Navigate(String address)
{
if (String.IsNullOrEmpty(address)) return;
if (address.Equals("about:blank")) return;
if (!address.StartsWith("http://") &&
!address.StartsWith("https://"))
{
address = "http://" + address;
}
try
{
webBrowser1.Navigate(new Uri(address));
}
catch (System.UriFormatException)
{
return;
}
}
// Updates the URL in TextBoxAddress upon navigation.
private void webBrowser1_Navigated(object sender,
WebBrowserNavigatedEventArgs e)
{
toolStripTextBox1.Text = webBrowser1.Url.ToString();
}
// Navigates webBrowser1 to the previous page in the history.
private void backButton_Click(object sender, EventArgs e)
{
webBrowser1.GoBack();
}
// Disables the Back button at the beginning of the navigation history.
private void webBrowser1_CanGoBackChanged(object sender, EventArgs e)
{
backButton.Enabled = webBrowser1.CanGoBack;
}
// Navigates webBrowser1 to the next page in history.
private void forwardButton_Click(object sender, EventArgs e)
{
webBrowser1.GoForward();
}
// Disables the Forward button at the end of navigation history.
private void webBrowser1_CanGoForwardChanged(object sender, EventArgs e)
{
forwardButton.Enabled = webBrowser1.CanGoForward;
}
// Halts the current navigation and any sounds or animations on
// the page.
private void stopButton_Click(object sender, EventArgs e)
{
webBrowser1.Stop();
}
// Reloads the current page.
private void refreshButton_Click(object sender, EventArgs e)
{
// Skip refresh if about:blank is loaded to avoid removing
// content specified by the DocumentText property.
if (!webBrowser1.Url.Equals("about:blank"))
{
webBrowser1.Refresh();
}
}
// Navigates webBrowser1 to the home page of the current user.
private void homeButton_Click(object sender, EventArgs e)
{
webBrowser1.GoHome();
}
// Navigates webBrowser1 to the search page of the current user.
private void searchButton_Click(object sender, EventArgs e)
{
webBrowser1.GoSearch();
}
// Prints the current document using the current print settings.
private void printButton_Click(object sender, EventArgs e)
{
webBrowser1.Print();
}
// Updates the status bar with the current browser status text.
private void webBrowser1_StatusTextChanged(object sender, EventArgs e)
{
toolStripStatusLabel1.Text = webBrowser1.StatusText;
}
// Updates the title bar with the current document title.
private void webBrowser1_DocumentTitleChanged(object sender, EventArgs e)
{
this.Text = webBrowser1.DocumentTitle;
}
// Exits the application.
private void exitToolStripMenuItem_Click(object sender, EventArgs e)
{
Application.Exit();
}
private void InitializeComponent()
{
this.components = new Container();
this.webBrowser1 = new System.Windows.Forms.WebBrowser();
this.menuStrip1 = new System.Windows.Forms.MenuStrip();
this.fileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.saveAsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator();
this.pageSetupToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.printToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.printPreviewToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripSeparator2 = new System.Windows.Forms.ToolStripSeparator();
this.propertiesToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.exitToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.toolStrip1 = new System.Windows.Forms.ToolStrip();
this.goButton = new System.Windows.Forms.ToolStripButton();
this.backButton = new System.Windows.Forms.ToolStripButton();
this.forwardButton = new System.Windows.Forms.ToolStripButton();
this.stopButton = new System.Windows.Forms.ToolStripButton();
this.refreshButton = new System.Windows.Forms.ToolStripButton();
this.homeButton = new System.Windows.Forms.ToolStripButton();
this.searchButton = new System.Windows.Forms.ToolStripButton();
this.printButton = new System.Windows.Forms.ToolStripButton();
this.toolStrip2 = new System.Windows.Forms.ToolStrip();
this.toolStripTextBox1 = new System.Windows.Forms.ToolStripTextBox();
this.statusStrip1 = new System.Windows.Forms.StatusStrip();
this.toolStripStatusLabel1 = new System.Windows.Forms.ToolStripStatusLabel();
this.menuStrip1.SuspendLayout();
this.toolStrip1.SuspendLayout();
this.toolStrip2.SuspendLayout();
this.statusStrip1.SuspendLayout();
this.SuspendLayout();
//
// webBrowser1
//
this.webBrowser1.Dock = System.Windows.Forms.DockStyle.Fill;
this.webBrowser1.Location = new System.Drawing.Point(0, 74);
this.webBrowser1.Name = "webBrowser1";
this.webBrowser1.Size = new System.Drawing.Size(704, 304);
this.webBrowser1.TabIndex = 0;
this.webBrowser1.Navigated += new System.Windows.Forms.WebBrowserNavigatedEventHandler(this.webBrowser1_Navigated);
//
// menuStrip1
//
this.menuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.fileToolStripMenuItem});
this.menuStrip1.Location = new System.Drawing.Point(0, 0);
this.menuStrip1.Name = "menuStrip1";
this.menuStrip1.Size = new System.Drawing.Size(704, 24);
this.menuStrip1.TabIndex = 3;
//
// fileToolStripMenuItem
//
this.fileToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.saveAsToolStripMenuItem,
this.toolStripSeparator1,
this.pageSetupToolStripMenuItem,
this.printToolStripMenuItem,
this.printPreviewToolStripMenuItem,
this.toolStripSeparator2,
this.propertiesToolStripMenuItem,
this.exitToolStripMenuItem});
this.fileToolStripMenuItem.Name = "fileToolStripMenuItem";
this.fileToolStripMenuItem.Size = new System.Drawing.Size(37, 20);
this.fileToolStripMenuItem.Text = "&File";
//
// saveAsToolStripMenuItem
//
this.saveAsToolStripMenuItem.Name = "saveAsToolStripMenuItem";
this.saveAsToolStripMenuItem.Size = new System.Drawing.Size(152, 22);
this.saveAsToolStripMenuItem.Text = "Save &As...";
this.saveAsToolStripMenuItem.Click += new System.EventHandler(this.saveAsToolStripMenuItem_Click);
//
// toolStripSeparator1
//
this.toolStripSeparator1.Name = "toolStripSeparator1";
this.toolStripSeparator1.Size = new System.Drawing.Size(149, 6);
//
// pageSetupToolStripMenuItem
//
this.pageSetupToolStripMenuItem.Name = "pageSetupToolStripMenuItem";
this.pageSetupToolStripMenuItem.Size = new System.Drawing.Size(152, 22);
this.pageSetupToolStripMenuItem.Text = "Page Set&up...";
this.pageSetupToolStripMenuItem.Click += new System.EventHandler(this.pageSetupToolStripMenuItem_Click);
//
// printToolStripMenuItem
//
this.printToolStripMenuItem.Name = "printToolStripMenuItem";
this.printToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.P)));
this.printToolStripMenuItem.Size = new System.Drawing.Size(152, 22);
this.printToolStripMenuItem.Text = "&Print...";
this.printToolStripMenuItem.Click += new System.EventHandler(this.printToolStripMenuItem_Click);
//
// printPreviewToolStripMenuItem
//
this.printPreviewToolStripMenuItem.Name = "printPreviewToolStripMenuItem";
this.printPreviewToolStripMenuItem.Size = new System.Drawing.Size(152, 22);
this.printPreviewToolStripMenuItem.Text = "Print Pre&view...";
this.printPreviewToolStripMenuItem.Click += new System.EventHandler(this.printPreviewToolStripMenuItem_Click);
//
// toolStripSeparator2
//
this.toolStripSeparator2.Name = "toolStripSeparator2";
this.toolStripSeparator2.Size = new System.Drawing.Size(149, 6);
//
// propertiesToolStripMenuItem
//
this.propertiesToolStripMenuItem.Name = "propertiesToolStripMenuItem";
this.propertiesToolStripMenuItem.Size = new System.Drawing.Size(152, 22);
this.propertiesToolStripMenuItem.Text = "Properties";
this.propertiesToolStripMenuItem.Click += new System.EventHandler(this.propertiesToolStripMenuItem_Click);
//
// exitToolStripMenuItem
//
this.exitToolStripMenuItem.Name = "exitToolStripMenuItem";
this.exitToolStripMenuItem.Size = new System.Drawing.Size(152, 22);
this.exitToolStripMenuItem.Text = "E&xit";
this.exitToolStripMenuItem.Click += new System.EventHandler(this.exitToolStripMenuItem_Click);
//
// toolStrip1
//
this.toolStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.goButton,
this.backButton,
this.forwardButton,
this.stopButton,
this.refreshButton,
this.homeButton,
this.searchButton,
this.printButton});
this.toolStrip1.Location = new System.Drawing.Point(0, 24);
this.toolStrip1.Name = "toolStrip1";
this.toolStrip1.Size = new System.Drawing.Size(704, 25);
this.toolStrip1.TabIndex = 2;
//
// goButton
//
this.goButton.Name = "goButton";
this.goButton.Size = new System.Drawing.Size(26, 22);
this.goButton.Text = "Go";
this.goButton.Click += new System.EventHandler(this.goButton_Click);
//
// backButton
//
this.backButton.Enabled = false;
this.backButton.Name = "backButton";
this.backButton.Size = new System.Drawing.Size(36, 22);
this.backButton.Text = "Back";
this.backButton.Click += new System.EventHandler(this.backButton_Click);
//
// forwardButton
//
this.forwardButton.Enabled = false;
this.forwardButton.Name = "forwardButton";
this.forwardButton.Size = new System.Drawing.Size(54, 22);
this.forwardButton.Text = "Forward";
this.forwardButton.Click += new System.EventHandler(this.forwardButton_Click);
//
// stopButton
//
this.stopButton.Name = "stopButton";
this.stopButton.Size = new System.Drawing.Size(35, 22);
this.stopButton.Text = "Stop";
this.stopButton.Click += new System.EventHandler(this.stopButton_Click);
//
// refreshButton
//
this.refreshButton.Name = "refreshButton";
this.refreshButton.Size = new System.Drawing.Size(50, 22);
this.refreshButton.Text = "Refresh";
this.refreshButton.Click += new System.EventHandler(this.refreshButton_Click);
//
// homeButton
//
this.homeButton.Name = "homeButton";
this.homeButton.Size = new System.Drawing.Size(44, 22);
this.homeButton.Text = "Home";
this.homeButton.Click += new System.EventHandler(this.homeButton_Click);
//
// searchButton
//
this.searchButton.Name = "searchButton";
this.searchButton.Size = new System.Drawing.Size(46, 22);
this.searchButton.Text = "Search";
this.searchButton.Click += new System.EventHandler(this.searchButton_Click);
//
// printButton
//
this.printButton.Name = "printButton";
this.printButton.Size = new System.Drawing.Size(36, 22);
this.printButton.Text = "Print";
this.printButton.Click += new System.EventHandler(this.printButton_Click);
//
// toolStrip2
//
this.toolStrip2.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.toolStripTextBox1});
this.toolStrip2.Location = new System.Drawing.Point(0, 49);
this.toolStrip2.Name = "toolStrip2";
this.toolStrip2.Size = new System.Drawing.Size(704, 25);
this.toolStrip2.TabIndex = 1;
//
// toolStripTextBox1
//
this.toolStripTextBox1.Font = new System.Drawing.Font("Segoe UI", 9F);
this.toolStripTextBox1.Name = "toolStripTextBox1";
this.toolStripTextBox1.Size = new System.Drawing.Size(250, 25);
this.toolStripTextBox1.KeyDown += new System.Windows.Forms.KeyEventHandler(this.toolStripTextBox1_KeyDown);
this.toolStripTextBox1.Click += new System.EventHandler(this.toolStripTextBox1_Click);
//
// statusStrip1
//
this.statusStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.toolStripStatusLabel1});
this.statusStrip1.Location = new System.Drawing.Point(0, 378);
this.statusStrip1.Name = "statusStrip1";
this.statusStrip1.Size = new System.Drawing.Size(704, 22);
this.statusStrip1.TabIndex = 4;
//
// toolStripStatusLabel1
//
this.toolStripStatusLabel1.Name = "toolStripStatusLabel1";
this.toolStripStatusLabel1.Size = new System.Drawing.Size(0, 17);
//
// Form1
//
this.ClientSize = new System.Drawing.Size(704, 400);
this.Controls.Add(this.webBrowser1);
this.Controls.Add(this.toolStrip2);
this.Controls.Add(this.toolStrip1);
this.Controls.Add(this.statusStrip1);
this.Controls.Add(this.menuStrip1);
this.Name = "Form1";
this.menuStrip1.ResumeLayout(false);
this.menuStrip1.PerformLayout();
this.toolStrip1.ResumeLayout(false);
this.toolStrip1.PerformLayout();
this.toolStrip2.ResumeLayout(false);
this.toolStrip2.PerformLayout();
this.statusStrip1.ResumeLayout(false);
this.statusStrip1.PerformLayout();
this.ResumeLayout(false);
this.PerformLayout();
}
protected override void Dispose(bool disposing)
{
if (disposing) { if (components != null) { components.Dispose(); } }
base.Dispose(disposing);
}
} -
fatal`
titán
válasz
pmonitor #9495 üzenetére
Kicsit kevered a dolgokat. Itt azért nincs külön designer fájl, mert kódból pakolja fel a controlokat a formra (nem is látszódnának a designerben VS alatt).
Designer által létrehozott fájlokat nem piszkálunk, mert felül fog íródni (vagy épp elszáll a designer ha hülyeséget írnak bele). Persze át lehet írni őket, csak nagyon figyelni kell (viszont a példád nem állja meg a helyét).
-
pmonitor
aktív tag
válasz
martonx #9482 üzenetére
a *.designer.cs fileokat nem szabadna módosítani.
Dehogynem szabad. Pl. itt a microsoft hivatalos oldalán sincs külön .designer file.
Úgyhogy nyugodtan lehet. Csak tudni kell, hogy mit csinál az ember fia. -
Alexios
veterán
válasz
DrojDtroll #9488 üzenetére
Unit/egyéb tesztek ahogy korábban is írták, ajánlott olvasmány: [link]
-
válasz
DrojDtroll #9488 üzenetére
Igen, úgy hívják a tool-t hogy unit teszt.
Tehát a refaktorálás előtt megírod a unit teszteket ha nincsenek, majd refaktorálsz és ellenőrzöd hogy továbbra is jók-e a tesztek.
-
disy68
aktív tag
válasz
DrojDtroll #9488 üzenetére
komponens tesztek, integrációs tesztek, end-to-end tesztek és opcionális manuál tesztelés a scope-tól függően
-
DrojDtroll
veterán
Sziasztok!
Van tool arra, hogy egy adott nagyobb rafaktorálás után kiderítsem, hogy a refaktorálás módosított-e valamit a program logikáján?
Sajnos olyan projektről van szó amihez semmi teszt nincs. -
Atomantiii
addikt
Jó hát nem fogom elvenni más programozóktól a kenyerüket, de nem is az a cél, hanem valamennyire bele szeretnék tanulni én is meló miatt is, hogy egyszerűbb dolgokkal elboldoguljak én is.
Illetve van egy saját programom is ami nagyon rég készült még visual basic 6-ban (egyébként még ma is működik win 10-en is), de elsődlegesen azt szeretném korszerűsíteni, ezért indultam el a windows forms app irányába. De most már így akkor értem, hogy hova írhatok és hova nem (célszerű).
-
Keem1
veterán
válasz
Atomantiii #9485 üzenetére
Nem fogod megbánni
Én még egy korai verzióján tanultam meg a C# alapokat (úgy, hogy már egyéb programnyelvből - delphi, php - voltak alapjaim).
Bár nem vagyok programozó, sőt, de C#-ban egy komplett kis utazási irodai rendszert készítettem úgy 5-6 év alatt, webes szinkronnal, mögöttes MySQL adatbázissal, 3-4 alkalmazott egyidejű használatára. Működött, de azóta lettek jobbak a piacon, különben még ma is működne, és ha én is ott dolgoznékAz jó, ha a konzolos alapok már megvannak, sőt, az is, ha esetleg korábbról más programozási nyelvi alapok is vannak, hisz akkor sokkal könnyebb egy új nyelvet elsajátítani.
Nézd, csak hogy tudd, nem vicceltem
-
Keem1
veterán
válasz
Atomantiii #9483 üzenetére
Ez esetben nem ártana egy C# alapok könyvet forgatni, ugyanis a *.designer.cs fájlokat az editor módosítja, nyilván a form vizuális módosításakor felülírja amit kézzel bele szerkesztesz.
Ez [link] egy elég jó alapot adó könyv, ha magyarul kellene ajánlani valamit.
Ja, és még egy jó tanács: egy új nyelv elsajátítását nem GUI programmal kezdjük, hanem konzolossal. Ha már mennek az alapok, alap programozási dolgok, objektumok, iterációk, öröklődés, streamek, stb, jöhet a gui
Ez azért is fontos, mivel akkor érsz el jó eredményt, ha tudod, mit csinál a vizuális editor egy gomb felhelyezésekor. Hisz mögötte az is kód. Akkor tanultad meg jól, ha már megy akár notepadból is egy form és a rajta lévő controlok felrakása kódból. -
martonx
veterán
válasz
Atomantiii #9481 üzenetére
Évtizedek óta nem winforms-oztam, de szvsz a *.designer.cs fileokat nem szabadna módosítani. Szóval rosszul álltál neki, rossz helyen módosítasz.
-
Atomantiii
addikt
válasz
DrojDtroll #9479 üzenetére
Akkor nekifutok még egyszer. Van egy windows forms app-om (.net frameworkos)
Szeretnék egy menühöz elemeket hozzáadni, pl most 2021-ben jelenjen meg az adott menüben 2021. Jövőre jelenjen meg ugyanabban a menüpontban 2021 helyett 2022.
Tehát a 0 helyett idén 2021 jelenleg meg, jövőre meg 2022, attól függ melyik évben vagyunk.Ekkor a form1.designer.cs-ben ez jelenik meg:
this.toolStripMenuItem3.Text = "0";
Ha ide beírom, az alábbi sort, akkor megjelenik a 0 helyett 2021 a menüben.
this.toolStripMenuItem3.Text = System.DateTime.Today.AddYears(0).ToString("yyyy");Ha a form1.designer.cs-ről átváltok form1.cs[design]-ra és ott mondjuk adok még hozzá menüket és utána visszaváltok form1.designer.cs-re, hogy az újaknak is megadjam a System.DateTime.Today.AddYears dolgait akkor azt látom, hogy a korábban beírt this.toolStripMenuItem3.Text = System.DateTime.Today.AddYears(0).ToString("yyyy"); helyett visszaírja ezt: this.toolStripMenuItem3.Text = "2021";
Vagy ez van olyan okos, hogy jövőre ide 2022-őt fog írni?
-
cigam
titán
válasz
Atomantiii #9478 üzenetére
Ezt a sort pontosan hova írod be?
-
DrojDtroll
veterán
válasz
Atomantiii #9478 üzenetére
Nem biztos, hogy értem a problémát.
Csak a designer-ben van gond?
-
Atomantiii
addikt
Kérlek ne nevessetek ki, még most ismerkedem a C#-al. Szóval szeretnék csinálni egy menüvel rendelkező programot visual studio 2019-ben, windows forms app-ként (net framework).
Eljutok odáig, hogy csinálok egy menustrip-et, hozzáadom a kívánt menüket, amikben évszámok is vannak. pl 2015, 2016, ... 2021.
De azt akarom elérni, hogy az adott menüben jövőre 1-el nagyobb évszám jelenjen meg. Ezt meg is tudom csinálni azzal, hogy beírom az adott menü elemének, hogy vonja ki az adott évet a mostaniból.
Pl this.toolStripMenuItem7.Text = System.DateTime.Today.AddYears(-1).ToString("yyyy");
De ha átváltok designer nézetből egy másikba, majd vissza designer nézetbe akkor ezt az előző sort átírja 2020-ra és törli azt. Hogyan lehetne elérni azt, hogy ne írja át az adott évre, hanem megmaradjon az hosszú formában?
-
cigam
titán
Egy kis logikai bukfencbe gabajodtam. Írtam egy stopper/visszaszámlálót.kb jól működik, de a vezérlése ravasz:
private void keyListening(object sender, KeyEventArgs e)
{
// Ha már fut a visszaszámlálás, nem engedi átváltani előreszámlálásra
if (e.Key == Key.F1 & !stopWatch.IsRunning)
{
reverse = false;
StartStopwatch();
}
if (e.Key == Key.F2) StopStopwatch();
if (e.Key == Key.F3)
{
reverse = false;
DeleteVariables();
}
if (e.Key == Key.F4) { Environment.Exit(0); ; }
// Ha má elindult a stopper, nem engedi átváltani visszaszámlálásra
if (e.Key == Key.F5 & !stopWatch.IsRunning)
{
reverse = true;
StartStopwatch();
}
if (e.Key == Key.F6) StopStopwatch();
if (e.Key == Key.F7)
{
reverse = true;
timeLimit = 10;
DeleteVariables();
}
if (e.Key == Key.F7)
{
reverse = true;
timeLimit = 10;
DeleteVariables();
}
if (e.Key == Key.Up & !stopWatch.IsRunning)
{
timeLimit++;
if (timeLimit > 30) timeLimit = 30;
minuteLabel.Content = timeLimit;
}
if (e.Key == Key.Down & !stopWatch.IsRunning)
{
timeLimit--;
if (timeLimit < 1) timeLimit = 1;
minuteLabel.Content = timeLimit;
}
}
Hogyan mondjam meg neki, hogy akkor se induljon el a stopper (F1), ha a visszaszámláló elérte a 0-át és megállt?
-
WaterWawe
őstag
Sziasztok!
Linuxos Docker konténerben használnék az alkalmazásommal Onnx modelt. A probléma, hogy ehhez a Nuget "Microsoft.ML.OnnxRuntime" egy natív könyvtárat hív és nem talál össze a megfelelő DLL-el (Vagyis Linuxon .so-val), hiába állítom be ezt külön. A Dockerfile a szükséges apt-get install-t tartalmazza.
A konkrét hibaüzenet:
System.TypeInitializationException: The type initializer for 'Microsoft.ML.OnnxRuntime.NativeMethods' threw an exception.
---> System.DllNotFoundException: Unable to load shared library 'onnxruntime' or one of its dependencies. In order to help diagnose loading problems, consider setting the LD_DEBUG environment variable: libonnxruntime: cannot open shared object file: No such file or directoryDockerfile parancsok:
...
WORKDIR /src
RUN apt-get update && apt-get install -y libgomp1
RUN export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/app/src/runtimes/linux-x64/native
... -
leslie23
tag
Sziasztok! Loosely coupled példát próbálok összerakni, MVP pattern használatával (WinForms).
Gondban vagyok, hogy jelen scenario esetén pontosan mi lenne nálam a Model. A MainFormon rendeléseket listázok (Order class példányai), egy SubFormon pedig lehetőség lenne a MainFormon kijelölt rendelés(ek) státuszának módosítására. A MainForm implementál egy IView interface-t, amin keresztül a MainFormhoz tartozó presenterrel történik a kommunikáció. Viszont a kérdés, hogy jelen esetben mi lenne a model? Egy repo, amely rendelkezik egy List<Order> mezővel?
Illetve a SubForm esetén ugyanez a kérdés, ha kijelöl 3 rendelést a user, akkor a SubForm modelje egy 3 elemű List<Order> lesz, amit a MainFormról adok át a SubForm megnyitásakor? -
wollnerd
aktív tag
Sziasztok!
Van egy kérdésem, amire magyarázatot szeretnék kapni hogy miért van ez.
Dolgozok egy idáig már 3 winform-os project-en. Amikor a 3. form-on kezdtem el dolgozni, átmenetileg átírtam a Program.cs-ben az Application.Run sorban arra a 3. form-ra hogy rögtön azt lássam.
Ma pedig végletesnek tituláltam a 3. form-ot és leprogramoztam az adatátvitel egy részét a 3. form-ra. Majd visszaírom a Program.cs-ben arra a fő ablakra. (Nos, valójában a főablak az induláskor elrejtve magát, mert behoz egy kisebb ablakot és azt leokézva felfedi magát a főablak a kisablakban megadott adatok átvitelével a főablakba.)
És azt láttam hogy egyszerűen nem akart elindulni a főform! (BlackjackWF) hajamat téptem, hiába tettem breakpoint-okat, de aztán meglepve rájöttem hogy... (kép alább)
És nem értem miért... Új típusú WinForm változó más névvel a welcomeform (a kisablak) alatt és mégis ez a 3. form megakadályozza főablak megjelenését!
Nem értem hogy miért és milyen programnyelvi utasítási szabályok alapján történik az, amit még a Debugger se mond el, sok-sok breakpointtal sem?!
Mindenesetre megnyugodtam, hiszen, ha nincs az a sor, szépen elindul a főablak, de ha aktív e sor, itt, akkor kapufa...Lehet hogy azt a sort jobb abba a button click event blokkjába helyezni, ahol megnyilna a 3. form...
-
pmonitor
aktív tag
válasz
joysefke #9471 üzenetére
Készítettem az eredeti OOP kódodra egy kis módosítást. Meg Készítettem 2 nem OOP metódust(az egyik static, a másikhoz példányosítani kell). A nem OOP metódusokban Array.Sort()-ok helyett quicksort-ot használtam. Ezek a kódok hasítanak! A kódokban a kiíratásokat kommenteztem ki(na meg az Array.Sort-ok helyét):
using System;
using System.Diagnostics;
namespace TesztConsole
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine(DateTime.Now);
//int i = 0;
int jmax = 25000;
Stopwatch sw = new Stopwatch();
long t_1 = 0, t_2 = 0, t_3 = 0, t_4 = 0, t_5 = 0, t_6 = 0, t_7 = 0;
sw.Start();
for (int j = 0; j < jmax; ++j)
{
var p = new Permutator("abcdananana".ToCharArray());
do
{
/*i++;
Console.WriteLine(new string(p.State));*/
}
while (p.Next());
//Console.WriteLine($"Nr of results: {i}");
}
t_1 = sw.ElapsedMilliseconds;
GC.Collect();
t_2 = sw.ElapsedMilliseconds;
for (int j = 0; j < jmax; ++j) new Program().Teszt_qsort("abcdananana".ToCharArray());
t_3 = sw.ElapsedMilliseconds;
GC.Collect();
t_4 = sw.ElapsedMilliseconds;
for (int j = 0; j < jmax; ++j)
{
var p = new Permutator_modositott("abcdananana".ToCharArray());
do
{
/*i++;
Console.WriteLine(new string(p.State));*/
}
while (p.Next());
//Console.WriteLine($"Nr of results: {i}");
}
t_5 = sw.ElapsedMilliseconds;
GC.Collect();
t_6 = sw.ElapsedMilliseconds;
for (int j = 0; j < jmax; ++j) stTeszt_qsort("abcdananana".ToCharArray());
t_7 = sw.ElapsedMilliseconds;
Console.WriteLine("Eredeti: {0}", t_1);
Console.WriteLine("Módosított: {0}", t_5 - t_4);
Console.WriteLine("Nem OOP: {0}", t_3 - t_2);
Console.WriteLine("Nem OOP static: {0}", t_7 - t_6);
}
static void QuickSort(char[] arr2, int p, int r)
{//quicksort
int Low, High;
char MidValue;
Low = p;
High = r;
MidValue = arr2[(p + r) / 2];
do
{
while (arr2[Low] < MidValue) ++Low;
while (arr2[High] > MidValue) --High;
if (Low <= High)
{
char T = arr2[Low];
arr2[Low] = arr2[High];
arr2[High] = T;
++Low;
--High;
}
} while (Low <= High);
if (p < High) QuickSort(arr2, p, High);
if (Low < r) QuickSort(arr2, Low, r);
}
int findCeilInt(char[] str, char first, int l, int h)
{
int ceilIndex = l;
for (int i = l + 1; i <= h; i++)
if (str[i] > first && str[i] < str[ceilIndex])
ceilIndex = i;
return ceilIndex;
}
void Teszt_qsort(char[] arr)
{
char[] tomb = (char[])arr.Clone();
int size = tomb.Length;
QuickSort(tomb, 0, size - 1);
//Array.Sort(tomb);
bool isFinished = false;
while (!isFinished)
{
int i;
/*for (int k = 0; k < size; ++k) Console.Write("{0} ", tomb[k]);
Console.WriteLine("");*/
for (i = size - 2; i >= 0; --i) if (tomb[i] < tomb[i + 1]) break;
if (i == -1) isFinished = true;
else
{
int ceilIndex = findCeilInt(tomb, tomb[i], i + 1, size - 1);
char temp = tomb[i];
tomb[i] = tomb[ceilIndex];
tomb[ceilIndex] = temp;
QuickSort(tomb, i + 1, size - 1);
//Array.Sort(tomb, i + 1, size - i - 1);
}
}
}
static int stfindCeilInt(char[] str, char first, int l, int h)
{
int ceilIndex = l;
for (int i = l + 1; i <= h; i++)
if (str[i] > first && str[i] < str[ceilIndex])
ceilIndex = i;
return ceilIndex;
}
static void stTeszt_qsort(char[] arr)
{
char[] tomb = (char[])arr.Clone();
int size = tomb.Length;
QuickSort(tomb, 0, size - 1);
//Array.Sort(tomb);
bool isFinished = false;
while (!isFinished)
{
int i;
//for (int m = 0; m < size; ++m) Console.Write("{0} ", tomb[m]);
//Console.WriteLine("");
for (i = size - 2; i >= 0; --i) if (tomb[i] < tomb[i + 1]) break;
if (i == -1) isFinished = true;
else
{
int ceilIndex = stfindCeilInt(tomb, tomb[i], i + 1, size - 1);
char temp = tomb[i];
tomb[i] = tomb[ceilIndex];
tomb[ceilIndex] = temp;
QuickSort(tomb, i + 1, size - 1);
//Array.Sort(tomb, i + 1, size - i - 1);
}
}
}
}
public class Permutator_modositott
{
public char[] State { get; }
int _size;
bool isFinished = false;
public Permutator_modositott(char[] symbols)
{
if (symbols?.Length > 0)
{
_size = symbols.Length;
State = (char[])symbols.Clone();
Array.Sort(State);
}
else
throw new ArgumentException("input must be non-empty");
}
public bool Next()
{
if (isFinished)
return false;
isFinished = !AdvanceState();
return !isFinished;
}
bool AdvanceState()
{
int i, j;
for (i = _size - 2, j = _size - 1; i >= 0; --i, --j)
if (State[i] < State[j])
break;
if (i == -1)
return false;
int ceilIndex = findCeil(State, State[i], i + 1, _size - 1);
char tmp = State[i];
State[i] = State[ceilIndex];
State[ceilIndex] = tmp;
Array.Sort(State, i + 1, _size - i - 1);
return true;
}
int findCeil(char[] str, char first, int l, int h)
{
int ceilIndex = l;
for (int i = l + 1; i <= h; ++i)
if (str[i] > first && str[i] < str[ceilIndex])
ceilIndex = i;
return ceilIndex;
}
}
public class Permutator
{
public char[] State { get; }
int _size;
bool isFinished = false;
public Permutator(char[] symbols)
{
if (symbols?.Length > 0)
{
_size = symbols.Length;
State = (char[])symbols.Clone();
Array.Sort(State);
}
else
throw new ArgumentException("input must be non-empty");
}
public bool Next()
{
if (isFinished)
return false;
isFinished = !AdvanceState();
return !isFinished;
}
bool AdvanceState()
{
int i;
for (i = _size - 2; i >= 0; --i)
if (State[i] < State[i + 1])
break;
if (i == -1)
return false;
int ceilIndex = findCeil(State, State[i], i + 1, _size - 1);
char tmp = State[i];
State[i] = State[ceilIndex];
State[ceilIndex] = tmp;
Array.Sort(State, i + 1, _size - i - 1);
return true;
}
int findCeil(char[] str, char first, int l, int h)
{
int ceilIndex = l;
for (int i = l + 1; i <= h; i++)
if (str[i] > first && str[i] < str[ceilIndex])
ceilIndex = i;
return ceilIndex;
}
}
}Az eredmény:
Eredeti: 46213
Módosított: 45772
Nem OOP: 14693
Nem OOP static: 14295Látszik, hogy a qsort alkalmazásával kb. harmada idő alatt lefutnak.
Érdemes lenne a rendezésre is csinálni teszteket.
De most nincs időm. -
joysefke
veterán
válasz
pmonitor #9470 üzenetére
1,
bent maradt a hot pathban a Console.WriteLine() ==> így nem lehet tesztelni. Ha kiveszed sokszorosára gyorsul majd. (csak akkor ugye hol lesz az eredmény)
2,
Nem készítesz a bemeneti tömbről másolatot (ami nem feltétlenül baj) de ez azt jelenti hogy a bemeneti tömböt az első futás első iterációja elött egy rendezéssel már tönkreteszed. az algo aztán folyamatosan pörgeti a tömböt míg annak a rendezése át nem fordul (növekvőről csökkenőre)Kizárólag az algoritmus felépítésének köszönheted (és nem a benchmark felépítésének) hogy a tömb amin dolgozol hiába teszed tönkre az algo minden futásával újrarendeződik és így minden futás az első kivételével pontosan ugyanannyi lépést jelent. Az elsőben a qsort ideje különbözni fog a többi futás qsortjának idejétől (de ez elhamyagolható)
-
pmonitor
aktív tag
válasz
joysefke #9468 üzenetére
Én így fordítottam át:
using System;
namespace IsmPerm
{
class Program
{
static int findCeilInt(int[] str, int first, int l, int h)
{
int ceilIndex = l;
for (int i = l + 1; i <= h; i++)
if (str[i] > first && str[i] < str[ceilIndex])
ceilIndex = i;
return ceilIndex;
}
static void Teszt_1(int[] tomb)
{ //https://www.geeksforgeeks.org/print-all-permutations-of-a-string-with-duplicates-allowed-in-input-string/
int size = tomb.Length;
Array.Sort(tomb);
bool isFinished = false;
while (!isFinished)
{
int x = 1, i;
for (int k = 0; k < size; ++k) Console.Write("{0} ", tomb[k]);
Console.WriteLine("");
for (i = size - 2; i >= 0; --i) if (tomb[i] < tomb[i + 1]) break;
if (i == -1) isFinished = true;
else
{
int ceilIndex = findCeilInt(tomb, tomb[i], i + 1, size - 1);
int temp = tomb[i];
tomb[i] = tomb[ceilIndex];
tomb[ceilIndex] = temp;
Array.Sort(tomb, i + 1, size - i - 1);
}
}
}
static void Main(string[] args)
{
int[] tomb = new int[] { 500, 500, 600, 600, 700};
Teszt_1(tomb);
Console.ReadKey();
}
}
} -
joysefke
veterán
válasz
pmonitor #9466 üzenetére
Átírva C#-ba és használható formában
A kezdeti 1x tömb-klónozáson kívül (hogy ne legyen elrontva a bemeneti tömb) teljesen allokációmentes.
A char[] State tárolja az aktuális állapotot, a bool Next() pedig lépteti az és visszajelez a sikerről. Ha a char[] State állapotot nem csak olvasni akarod akkor értelemszerűen ki kell menteni róla egy másolatot.A char[] State köré lehetne még valami readonly wrappert rakni, de azt nem tudom hogy viselkedne.
char[] megy bele ctor bemeneti paraméterként
És ezen még lehetne gyorsítani.
using System;
namespace Permutator
{
class Program
{
static void Main(string[] args)
{
int i = 0;
var p = new Permutator("abcdananana".ToCharArray());
do
{
i++;
Console.WriteLine(new string(p.State));
}
while (p.Next());
Console.WriteLine($"Nr of results: {i}");
}
}
public class Permutator
{
public char[] State { get; }
int _size;
bool isFinished = false;
public Permutator(char[] symbols)
{
if (symbols?.Length > 0)
{
_size = symbols.Length;
State = (char[])symbols.Clone();
Array.Sort(State);
}
else
throw new ArgumentException("input must be non-empty");
}
public bool Next()
{
// if we have already finished we indicate failure on getting next element
// else we try to advance the state and propagate success of advancing state
if (isFinished)
return
false;
isFinished = !AdvanceState();
return !isFinished;
}
bool AdvanceState()
{
// Find the rightmost character
// which is smaller than its next
// character. Let us call it 'first
// char'
int i;
for (i = _size - 2; i >= 0; --i)
if (State[i] < State[i + 1])
break;
// If there is no such character, all
// are sorted in decreasing order,
// means we just printed the last
// permutation and we are done.
if (i == -1)
return false;
// Find the ceil of 'first char'
// in right of first character.
// Ceil of a character is the
// smallest character greater
// than it
int ceilIndex = findCeil(State, State[i], i + 1, _size - 1);
char tmp = State[i];
State[i] = State[ceilIndex];
State[ceilIndex] = tmp;
Array.Sort(State, i + 1, _size - i - 1);
return true;
}
// This function finds the index of the
// smallest character which is greater
// than 'first' and is present in str[l..h]
int findCeil(char[] str, char first, int l, int h)
{
// initialize index of ceiling element
int ceilIndex = l;
// Now iterate through rest of the
// elements and find the smallest
// character greater than 'first'
for (int i = l + 1; i <= h; i++)
if (str[i] > first && str[i] < str[ceilIndex])
ceilIndex = i;
return ceilIndex;
}
}
}
-
pmonitor
aktív tag
válasz
joysefke #9464 üzenetére
Átírtam C#-ba, meg összehasonlítottam az én kódommal. 5-ször gyorsabb amit Te linkeltél. Jól tudsz guglizni. Köszönöm!
De egyébként ezt is ugyanazzal a módszerrel teszteltem, mint a tömbök másolását. És itt is ugyanolyan konzekvensen mutatta az eredményt, mint ott. Úgyhogy a tesztelés sémájával nincs semmi gond. Azt teszteli, amit tesztelni szeretnék. Ezzel teszteltem:
static void Main(string[] args)
{
tomb = new int[] { 500, 500, 600, 600, 700 };
int max = 5000000;
Stopwatch sw = new Stopwatch();
long t_1 = 0, t_2 = 0, t_3 = 0;
sw.Start();
for (int i = 0; i < max; ++i) Teszt_1(tomb);
t_1 = sw.ElapsedMilliseconds;
GC.Collect();
t_2 = sw.ElapsedMilliseconds;
for (int i = 0; i < max; ++i) Teszt_2(tomb);
t_3 = sw.ElapsedMilliseconds;
Console.WriteLine("{0} {1}", t_1, t_3 - t_2);
Console.ReadKey();
} -
pmonitor
aktív tag
válasz
joysefke #9462 üzenetére
A teszt mér valamit, de nem azt amire te kiváncsi vagy.
Amíg konzekvensen ugyanazt az eredményt írja ki, addig nekem tökéletes. Ráadásul kipróbáltam. A Cutter programomban az Array.Copy()-t lecseréltem a CopyMemory()-ra, és ugyanazt a tendenciát mutatta, mint a teszt programom. Gyorsabb lett. Tehát sztem azt méri, amit szeretnék mérni. A Cutter program futásakor is "lutri", hogy mikor indul be a GC, tehát még ez is élethűen van a tesztben.
Csak az a baj, hogy(mint ahogy először jól mondtad), a stackalloc a stack-en allokál. Ezt pedig sajnos nem engedhetem meg magamnak(a stack is véges, és mivel nem tudom, hogy egyszerre mennyire van szükségem, ezért ez nem megoldás.), mindenképp a heap-ben kell allokálnom.
-
joysefke
veterán
válasz
pmonitor #9463 üzenetére
Ha ez a feladat akkor én itt egyetlen tömbfoglalást sem látok:
Print all distinct permutations of a given string with duplicates - GeeksforGeeks -
pmonitor
aktív tag
válasz
joysefke #9462 üzenetére
Ha nem kell a mélységi bejárás során keletkező összes tömböt megtartani, csak mindig 1-1 újabbra van szükséged és tudod hogy egy tömbre mikor nem lesz már szükség
Rekurzív hívásokról van szó. Tehát nem mindig csak egyet kell megtartani. Viszont még azt sem lehet előre tudni, hogy egyidőben mennyire van szükség.
-
joysefke
veterán
válasz
pmonitor #9461 üzenetére
De ez az összes többi esetre is vonatkozik(teszt_1-teszt_5-ig). Nem állítom, hogy a teszt atompontos. De többször lefuttattam, és mindig hasonló eredményt adott az egymáshoz viszonyított idők tekintetében.
A teszt mér valamit, de nem azt amire te kiváncsi vagy.
Az optimalizálás 5letét az ismétléses permutáció algoritmusa adta. Ott nagyon sokat kell allokálni és feltölteni(bár a legjobb az lenne, ha csak feltölteni --tehát simán másolni-- kellene).
Ha nem kell a mélységi bejárás során keletkező összes tömböt megtartani, csak mindig 1-1 újabbra van szükséged és tudod hogy egy tömbre mikor nem lesz már szükség, akkor érdemes lehet ezt kipróbálni. Ezzel ki tudod küszöbölni a heap allokációt. Én még nem használtam.
-
pmonitor
aktív tag
válasz
joysefke #9460 üzenetére
Ha nagyot foglalsz a heapen akkor az triggerelhet egy GC futást is.
De ez az összes többi esetre is vonatkozik(teszt_1-teszt_5-ig). Nem állítom, hogy a teszt atompontos. De többször lefuttattam, és mindig hasonló eredményt adott az egymáshoz viszonyított idők tekintetében.
Csak másolni kell a tartalmat egyik helyről a másikra vagy allokálni kell és feltölteni? Elég jelentős a különbség.
Az optimalizálás 5letét az ismétléses permutáció algoritmusa adta. Ott nagyon sokat kell allokálni és feltölteni(bár a legjobb az lenne, ha csak feltölteni --tehát simán másolni-- kellene).
(nem ismerem a feladatot)
A webhelyemen lévő tesztben allokálok és feltöltöm. A konkrét feladat pedig az ismétléses permutáció algoritmusa(ami a teszthez az 5tletet adta).
-
joysefke
veterán
válasz
pmonitor #9458 üzenetére
static unsafe void teszt_6(int[] source, int n)
{
int[] dest = new int[n];
fixed (int* pSource = source, pdest = dest)
{
int* pSource_0 = pSource;
int* pdest0 = pdest;
int* pmax = pSource_0 + n;
for (; pSource_0 < pmax; ++pSource_0, ++pdest0)
{
*pdest0 = *pSource_0;
}
}
}
mivel a metódusnak visszatérési értéke nincsen (void), a program végeredménye szempontjából lényeges mellékhatás sincsen (nincsen IO, nem változtat semmilyen állapotot) ezért ezért honnan tudod, hogy futás közben release + optimalizáció beállítással ez egyáltalán lefut? (valószínűleg lefut, de nem kéne)
Ráadásul a timert úgy indítod-állítod le, hogy a memóriamásoláson kívül szinte minden tesztesetedben van ciklikus heap allokáció is. Ha nagyot foglalsz a heapen akkor az triggerelhet egy GC futást is.
Mivel a teszt-metódusaidat ciklusban futtatod, az iterációk között teleszemeteled a heapet halott objektumokkal ezért FOG futni a GC, többször, sokszor. A GC futás valószínűleg több időbe kerül mint maga a memóriamásolás. (pld mert a memóriaterületeket valamikor nullázni is kell stb) . Innentől kezdve a méréseid pontatlanok.
Ha memóriát akarsz kézzel másolni, akkor #9455 szigorúan allokáció nélkül. az kimaxolja a mem sávszélt, az a másolás sebességének elméleti határa
====
Az egészet arra éleztem ki, hogy a "fő programom"(a cutter) esetében sokat kell tömböt másolni. Igaz, hogy csak kis méretűeket.
Csak másolni kell a tartalmat egyik helyről a másikra vagy allokálni kell és feltölteni? Elég jelentős a különbség. (nem ismerem a feladatot)
====
A legnagyobb meglepetést azonban az Unsafe kód okozta. Kis méretű tömb esetén a "középmezőnyben" van. Nagy méretű tömb esetén azonban lényegesen a leggyorsabban végez az összes többinél.
Két oka van:
1,
Az eredeti unsafe teszt-metódusodban nem volt for ciklusos heap allokáció hanem stackalloc volt => nincs GC a szemét eltakarítására, összehasonlíthatatlanul gyorsabb. Az összes többi teszt ahol new int[n] hívódik ciklikusan hatalmas handikeppel indult...
2,
Az unsafe kikapcsolja a tömb hozzáférések során az indexer értéktartomány ellenőrzését. ezzel csökkentetted a ciklusonkénti munkát (indexer értékhatár ellenőrzés + mem másolás helyett csak mem másolás). Gondolom a többi library metódus is unsafe-ként van belül megvalósítva. Csak ugye lsd 1. pont -
pmonitor
aktív tag
válasz
pmonitor #9458 üzenetére
Az egészet arra éleztem ki, hogy a "fő programom"(a cutter) esetében sokat kell tömböt másolni. Igaz, hogy csak kis méretűeket. És ezt rekurzívan kell tenni(ismétléses permutáció generálásához). A Win api CopyMemory() esetén lényegesen gyorsabb lett az ismétléses permutáció generálása(a rekurzív hívásokban lévő tömb másolások gyorsulása miatt.) .
-
pmonitor
aktív tag
válasz
joysefke #9455 üzenetére
Igaz. Közben rájöttem.
Ez lenne talán a reális:
static unsafe void teszt_6(int[] source, int n)
{
int[] dest = new int[n];
fixed (int* pSource = source, pdest = dest)
{
int* pSource_0 = pSource;
int* pdest0 = pdest;
int* pmax = pSource_0 + n;
for (; pSource_0 < pmax; ++pSource_0, ++pdest0)
{
*pdest0 = *pSource_0;
}
}
}Szerk.: És ez már megint csak akkor végez, mint az első esetben(tehát mégsem a leggyorsabb). Azért érdekes, hogy attól, hogy unsafe, még nem optimális kódot lehet vele írni.
-
joysefke
veterán
válasz
pmonitor #9454 üzenetére
Nem derül ki, hogy mit akarsz csinálni. És mi alapján választottad ki a bementő paramétereket.
static unsafe void teszt_5(int[] source, int n)
{
fixed (int* pSource = source)
{
int* dest = stackalloc int[n];
int* pSource_0 = pSource;
int* pmax = pSource_0 + n;
for (; pSource_0 < pmax; ++pSource_0, ++dest)
{
*dest = *pSource_0;
}
}
}
(1)
bemegy egy tömb és egy int.(2)A stacken foglalsz egy int tömböt
-ami nem tudja elhagyni a stacket
-és nem lehet nagyobb mint a stack mérete (ráadásul a stackből foglalja a helyet aminek a metódus hívásakor már van egy a metódus számára ismeretlen mérete illetve a default stackméret futtatókörnyezettől is függ)(3)aztán feltöltöd az int[n] tömböt és
(4)elfelejtedHa kézzel írnék tömbmásolásra egy UNSAFE metódust akkor bemenetként a már lefoglalt cél és forrástömb referenciáit vinném be aztán SIMD-del 32 byteonként másolnék (AVX register mérete).
Amit te csinálsz ott egy int* pointert inkrementálsz és int méretben történik az adatmozgatás. (a mivel a ciklusok nem függenek az előzőektől ezért jó esetben 3-4 átlapolva történik meg)
SIMD-del egyedül a memória sávszélessége szabna határt
-
pmonitor
aktív tag
Érdekes dolog ez az optimalizálás. Én éppen most írtam 1 tesztprogramot tömbök másolásához. Elég érdekes dolgok jöttek ki. Ért 1-2 meglepetés...
-
leslie23
tag
válasz
Marky18 #9452 üzenetére
Jogos a kérdés, maga a tárolt eljárás egyszerű, az adatok mennyisége sem nagy. Viszont a DB nem localhoston van, hanem távoli gépen, amihez VPN-en keresztül csatlakozom. Gondolom ezért, de az SqlConnection.Open 1-1 másodpercre megakasztja a műveleteket, ha debuggerrel megyek végig a kódon.
A kapcsolatot minden lekérdezés előtt felépítem, de ha jól tudom, ilyenkor van connection pooling. Hogyan lehetne másképp? Gondolom nyitva nem tarthatom a SqlConnectiont.
Ami még időigényes lépésnek tűnik az egy foreach a DataGridViewColumn objecteken, közben AutoSizeMode property állítása ColumnName függvényében. Furcsa, de debug mode-ban ez is 1 másodperc mire lefut, pedig eventet nem hívok közben és 12 oszlop (és olyan 50 sor) az egész. -
Marky18
aktív tag
válasz
leslie23 #9451 üzenetére
Az async-await pattern minden GUI-s alkalmazashoz ajanlatos.
En ott kezdenem a kutakodast, hogy miert tart a DB-tol a Viewig 3-4 masodpercig az adatbetoltes? Tarolt eljarasokkal szamolod on-the-fly a betoltendo adatot? Nem lenne egyszerubb ezt DB oldalon letarolni es csak egy jol iranyzott SELECT-el lekerdezni? Mindenkeppen user interakciora kell betoltened az adatot? A lekerdezes elott epited fel a DB connectiont vagy mar elore felepited?
Itt a bottleneck a DB query lesz szerintem, ha azt kikuszobolod es hasznalod az async-await patternt, akkor nem fog varakozni a main thread es a betoltes sem fog masodpercekig tartani. -
leslie23
tag
Sziasztok!
Egy egyszerű kliensen dolgozom WinFormsban, néhány ablakból fog állni az egész app. Tudom, hogy elavult, meg stb., csak nem akartam fejest ugrani a WPF-be.
A problémám, hogy a formok megjelenítésekor az adatok lekérése (tárolt eljárások) miatt 3-4 sec, mire megjelenik kattintástól számítva egy-egy form. Mit tudnátok javasolni erre?Már az is előrelépés szerintem, ha megjelenik a form, de a DataGridView helyén mondjuk egy loading spinner van, amíg az adatok és a renderelés el nem készül. Olvastam, hogy a BackgroundWorker felejtős, láttam példát async/await implementációra, de érdekelne, hogy általánosságban desktop appoknál szokás-e ezzel foglalkozni és ha igen, akkor létezik-e best practice?
-
joysefke
veterán
válasz
Flashback #9445 üzenetére
Ezt Databindinggal és ObservableCollectionnel szokás megoldani, illetve amikor a user a GUI-n a lista aljára ér, akkor ott keletkezhet egy event amire feliratkozhat a kódod, arra reakcióként pedig betöltheted a következő oldalt (hozzáadod az ObservableCollection-höz, a databinding pedig onnantól elintézi a többit) mondjuk Xamarin.forms-ban ez lenne.
Gondolom oka van hogy nálad így lett megoldva...
-
dqdb
nagyúr
válasz
Flashback #9447 üzenetére
A struct ugyanúgy bővíthető metódusokkal, ez nem C, C#-ban a struct mást jelent, mint C-ben. A fenti linkemen a mikor használj structot class helyett listában négyből három feltételt nem teljesít a kódod:
* It logically represents a single value, similar to primitive types (int, double, etc.).
* It has an instance size under 16 bytes.
* It is immutable. -
válasz
Alexios #9438 üzenetére
Kösz ezt kerestem
Ez a struct egy globális változó. Van ilyenből még 2-3 darabom és mindegyikkel kb ua. kell csinálom.
joysefke
Egy kicsit speciális az eset. Ezek a structok speciális "listák" egy adatbázisból olvasok bele. Majd bizonyos függvények listázzák és a structban van eltárolva hogy a GUI-n éppen hol tart a lista. Ezeket az index paramétereket módosítom.
Lehetne máshogy felépíteni?
Jelenleg ez a szerkezete:public struct myCustomList
{
public string listName;
public List<Items> items;
public int onePageElement;
public string actState;
public int ListIndex;
public int pages;
public int actpage;
public string title;
} -
martonx
veterán
válasz
joysefke #9435 üzenetére
Jaj, ne is mondd, most tárgyalok épp egy céggel, akikhez lehet átmennék, és mindenképpen laptopot akarnak adni, én pedig mindenképpen asztali gépet szeretnék (az nekem nem baj, ha adnak laptopot IS).
Itthonról Ryzen 5 3600-on dolgozok PCIe4-es SSD-vel, tuning ramokkal. Ezt a gépet összevetni a régi céges i7-6700, SATA SSD-vel, háááát ég és föld.
Nem értem miért kell a cégeknek úgy tenniük, mintha csak laptopról lehetne rugalmas (home office és irodai, mikor hogy) munkát végezni. -
joysefke
veterán
Nekem is Lenovo volt előtte (Thinkpad T470p szintén 45W procival -4/4 i5-). Ennek 14"-os létére jobb volt a hűtése mint a 15"-os fém és jóval nehezebb Dellnek. A gép egyszerűbb volt, de jobb.
A vállalati Windows alatt azt értem, hogy nálunk egy külön enrollment image van, amit fel kell dobni a gépre.
Nálunk szerencsére nem. Semmi custom vacak nincsen. Szinte minden megy internetről VPN nélkül AzureAD SSO-val. Mint egy álom.
A Windowsban a notepad is többet ér használhatóságban mint ez a noti. egy haszna van: A nagy fényes érintésérzékeny kijelző hétvégén vidéken jól kezelhető fekve az ágyban netezésre filmnézésre.
-
Keem1
veterán
válasz
joysefke #9440 üzenetére
Mondjuk persze így más a leányzó fekvése, ha maga a gép szar.
A Lenovo-k minden téren jók, én amúgy meg vagyok velük elégedve, ha a civil életben is szükségem lenne laptopra, biztos hogy Lenovo lenne, hiába k*va drága.A vállalati Windows alatt azt értem, hogy nálunk egy külön enrollment image van, amit fel kell dobni a gépre. Ez gyalulja az SSD-t, titkosítja azt, beloggol a céges rendszerbe, ellenőrzi, hogy mid van (szoftver, windows, office), aztán felpakolja azokat, meg az alap céges dolgokat is, beállítja a vpn-t, proxy-t, és még sorolhatnám a listát sokáig.
Na, az enroll szoftverekben van ami rendkívül procizabáló, beleértve a nagyvállalati McAfee-t is. Nyilván az utolsó billentyűleütést is monitorozza, de azért mégis érdekes az, hogy egy sima konzumer windows-zal minden probléma eltűnik.
-
joysefke
veterán
válasz
Flashback #9437 üzenetére
A többiek jól mondják, a ref kulcsszó kell neked, de már a kérdésből gyanús, hogy valamit nem úgy csinálsz ahogy illene:
Ha átadsz egy inicializált List-et paraméterként egy metódusnak, akkor ez esetek nagy részében ezt azért kéne tegyed, hogy a metódus olvassa a List-et, esetleg módosítsa a tartalmát (feltöltse vagy hozzáadjon) és nem azért, hogy a kapott referenciát megváltoztasd és ezáltal az eredeti List adatszerkezetet eldobd. Ha az eredeti List-re nem mutat másik referencia akkor az GC-zve lesz. Mi értelme volt akkor elötte inicializálni?
Ha új listát akarsz létrehozni, akkor érdemesebb lenne azt a metóduson belül megtenni és annak visszatérési értékeként visszaadni. Ebben az esetben viszont nem illik semmilyen bemenő paramétert megváltoztatni.
-
joysefke
veterán
Szerintem ez leginkább a vállalati Windowsok átka lesz.
Köze nincs a Windows-hoz. A Dell notebook (Precision 5540) egy szemét arra tervezték, hogy a 15-precre amire egy beszerzésért felelős vezető a kezébe veszi jó benyomást keltsen, nem arra, hogy ezt valaki 8 órában használni is akarja, főleg nem erőforrásigényes dolgokra.
Ha a Visual Studio beindul, (vagy bármi más) akkor a háttérfolyamatai felfalják a notit, pillanat alatt megeszi a turbó/hő-keretét és utána már csak 2.6GHz-en vagy alatta szerencsétlenkedik olyan hanggal mintha egy flex lenne. Es akkor már akkor sem fog felugrani 4.6GHz-re, ha olyan burstos folyamat van aminek tényleg kéne (UI vagy bármi aminek prioritása van a VS background taskokkal szemben).
Egyértelműen tervezési / beszerzési hibás ez a gép. Zabáló túlhevülő processzor egy vékony gyenge hűtésű házban.
Szerintem ez leginkább a vállalati Windowsok átka lesz.
Ezeken vállalati Windowst futtatnak. Az 5530-on konkrétan fagyott a Linux (nálunk). A Dell képzeletbeli operációs rendszerekhez fejleszti a gépeit?.
-
Sziasztok
Objektum orientált kérdésem lenne.
Van egy saját struktúrám hívjuk customList -nek.
Form létrehozásánál rögtön példányosítok egyet:private customList myList = new customList ();
Majd az egyik függvényemmel módosítani szeretném az értékét. Kb így néz ki:
private void changeState(myList list)
{
érték módosítás
}
Na és itt jön a problémám hogy az átpasszolt listátból létrehoz a függvény magának egy példányt és nem változik az értéke az átadott listámnak. Próbáltam static-al példányosítani de ugyanaz.
Persze ha visszadom a függvény visszatérési értékének a listát és azt egyenlővé teszem a customListámmal akkor jó, de az nem túl elegáns.
Hogy tudnám rávenni hogy az én példányomat módosítsa a függvény?
C-ben átadnám a pointert... -
Keem1
veterán
válasz
joysefke #9435 üzenetére
Szerintem ez leginkább a vállalati Windowsok átka lesz.
Az én céges Lenovomban egy i7 8665U van, ami a cégesszemétfeature-ök miatt eléggé ki van hajtva. A régi gép, amit erre cseréltem, az i5 procival, mezei konzumer Windows-zal sokkal gyorsabb, mint az új a vállalatival. -
joysefke
veterán
válasz
martonx #9434 üzenetére
Hmm nekem egy i7 9850H -val szerelt 15"-os "business" Dell noti van. Nem az én ötletem volt a régit erre cserélni.
A legkisebb terhelésre is behangosodik, ha pedig komoly terhelés van (nagy repo+ VS-E + debuggolás), akkor olyan mintha flexelnének mellettem. Az órajeleket egy pillanat alatt visszaveszi 2.6GHz-ra -lehet hogy az alá is-, aztán még a MS Teams is akad rajta. Miközben órákon keresztül úgy üvölt hogy a saját gondolataimat sem hallom...
Valószínűnek tartom, hogy ha kipróbálom, a PC-mben lévő RyZEN 3100 is tényleges munka alatt agyonveri ezt a mobil i7-et. Biztosan nem fog sem üvölteni vagy 3.9GHz alá visszevenni az órejelét.
Mindenki számára intő példa legyen, aki azt hiszi hogy ezek a "business" laptopok bírják a terhelést...
-
joysefke
veterán
válasz
drsanya #9428 üzenetére
semmi köze a típusossághoz. var-ral is már megvan fordítási időben a változó típusa.
Egyrészt nincs sok haszna deklarációnál bal oldalra kiírni a típust ha az értékadásból már ránézésre látszik, hogy mi a típus.
Másrészt nehezíti a szerkesztést: lehet hogy le akarom cserélni a változó típusát vagy azon belül mondjuk egy generikus típusparamétert egy kompatibilisre stb. Ha bal oldalon fixen benne van a deklarációban a típus, akkor oda kell menni és manuálisan ki kell cserélni. Feleslegesen. LINQ-nél meg persze halál lenne. -
drsanya
aktív tag
-
joysefke
veterán
kicsit off.
Van egy nyomorék céges laptopom ami üvölt mint egy turbina, de legalább lassú mint a csiga (9-gen top i7
) és fontolom hogy a privát gépemre költöztessem a munkát legalább akkor amikor otthonról dolgozom mert az kussban van és még az órajeleit is tudja tartani szemben a laptoppal.
SSD-t kéne bővítenem amin a céges VM+ VS lenne. Kérdés hogy a VS Entrprisenak mennyire kell a minnél gyorsabb SSD? Fordítás meg a kódanalízis mennyire szereti a gyorsabb SSD-t (WD black vagy Crucial P5) egy alsóbb kategóriással szemben (WD blue vagy Crucial P2)?
-
"Ha ciklusokkal operálsz, akkor neked kell felvenni a végeredmény változót, gondoskodni a megfelelő sorrendben való kereséshez, satöbbi."
Ahogy mondod. A tanulás elején pedig nem árt ha megtanulod milyen módon működnek ezek a dolgok.
"LINQ egyes esetekben sokkal optimálisabb."
Ezzel egyetértek.
-
vlevi
nagyúr
válasz
drsanya #9420 üzenetére
Akkor még nem volt LINQ.
Én sem szeretem használni a var-t, de a LINQ használata esetén nem tudod, hogy milyen típusú ojjektumot ad vissza. Sokszor csak egy IEnumerable interfészt, aminek az elemei valamilyen ideiglenesen összeállított classból vannak.
Ha pl. két listát kapcsolsz össze azonosító alapján, és azokból kell neked valami."célszerűbb lenne ha ciklusokat használva LINQ helyett."
Igaz is, meg nem is. Ha elkezd ciklusokat írni, akkor azzal lesz tele a kód a tényleges feldolgozás helyett, és abban is lehet hibát véteni. Ha leír egy egysoros LINQ kifejezést, akkor azzal egy sorban meg van oldva a keresés.
Ha ciklusokkal operálsz, akkor neked kell felvenni a végeredmény változót, gondoskodni a megfelelő sorrendben való kereséshez, satöbbi.
Az viszont igaz, hogy kezdőként meg kell ismerni az alapokat, ezért néha jó, ha használja, de a LINQ egyes esetekben sokkal optimálisabb.
Harmadrészt viszont lehet ülni félórákat egyetlen gomblenyomás nélkül, mire kiagyalod a megfelelő LINQ szintatkikát ahhoz, hogy pl. két listából összeválogass magadnak valamit. -
PuMbA
titán
válasz
kw3v865 #9416 üzenetére
A lista[0]-hoz az első sorodban látszik, hogy ezt adtad hozzá: "new SprayingData(){ dozis = 1, allapot = 3}". Tehát a lista[0]-nak nincs olyan property-je, hogy lista[0].allapot.
Megoldani úgy lehet, hogy List<int> allapotok = lista.First().Select(x => x.allapot).ToList();
-
martonx
veterán
válasz
kw3v865 #9416 üzenetére
Megjegyzés 1: nagyon gyorsan felejtsd el a magyar változó neveket. Sírni tudnék, ahányszor magyar/német/bármi ami nem angol változóneveket látok.
Megjegyzés 2: használd a LINQ-t. pl nem lista[0] hanem lista.First() máris sokkal szebb, olvashatóbb.
És valami ilyesmi fog neked kelleni:
var states = myList.First().Select(item => item.state);
Ha ragaszkodsz az array kimenethez, akkor egy ToArray()-t is érdemes a végére csapni.
-
kw3v865
senior tag
Hú, tényleg, köszönöm mindkettőtöknek! Így már működik
.
Azonban továbbhaladva, ismét megakadtam. A lista most így van feltöltve:lista[0].Add(new SprayingData(){ dozis = 1, allapot = 3});
lista[0].Add(new SprayingData() { dozis = 2, allapot = 4 });
lista[1].Add(new SprayingData() { dozis =4, allapot = 1 });
A célom az lenne, hogy a 0-ás indexűből kiszedjem egy tömbbe az összes állapot értéket.
Tehát az új tömbnek ezeket az értékeket kellene tartalmaznia: 3,4.
Így próbáltam, de ez nem jó:int[] allapotok = lista[0].allapot;
Hogyan lehetne ezt megoldani szerinted?
-
fatal`
titán
válasz
kw3v865 #9413 üzenetére
Nem hoztad létre a belső listát.
Először lista.Add(new List<adatok>());
Majd utána lista[0].Add(new adatok());
Utána már állítgathatod az állapotát, nyilván több elem esetén ciklusok fognak kelleni.
A konvenció szerint az osztályok és a propertyk nevét nagybetűvel kezdjük (Adatok, Dozis, Allapot).
-
kw3v865
senior tag
Sziasztok!
C#-ban létrehoztam egy osztály, így:
public class adatok
{
public int dozis { get; set; }
public int allapot { get; set; }
}
Ezt követően egy 2D-s listát, melynek típusa az adatok osztály:
List<List<adatok>> lista = new List<List<adatok>>();
A problémám az, hogy nem tudok ehhez hozzáadni semmit.
Se így:lista[0][0].allapot = 1;
Se így: lista[0].Add(new SprayingData(){ dozis = 1, allapot = 3});OutOfRangeException-t dob.
Van esetleg valami tippetek, mi okozhatja a problémát? Vajon mit rontottam el?
-
Keem1
veterán
válasz
sztanozs #9411 üzenetére
Most egyelőre ez így műxik, átírtam egy registry értéket, így már IE 11 az embedded browser. Néha még megpattint egy-egy javascript hibaüzenetet, de működik. Megy amúgy is, csak idegesítő lekattintani egymás után vagy 8-10 db errort.
A dolognak nincs akkora súlya hogy tovább agyaljak rajta, egyelőre így marad.
Köszi srácok, mindenkinek.
-
-
Keem1
veterán
válasz
martonx #9409 üzenetére
Persze, de a kollégákban nem ébresztene bizalmat, hogy az SSO-jukat elkéri a programom, ami aztán bármit kezdhet vele, akár tárolhatja is.
Nyilván ha akarnék, ezzel a módszerrel is vissza tudnék élni, de egy fokkal bizalomgerjesztőbb, hogy a szokásos login page jön be, jobbklikk-properties és látják a megszokott https://blablabla.com/login.jsp-t.
Ezért az ötlet az OAUTH2-féle login, ahol csak az access tokent (jelen esetben a cookie-ból) megkapva mehet minden tovább. -
Keem1
veterán
válasz
martonx #9406 üzenetére
Az ám, csak kell a login page, és utána a kapott cookie. A logina adataimat meg be kéne írni a webes login oldalon.
Nem elegáns, de a jobb megoldás megtalálásáig olyat csináltam, hogy a registryben egy dword-öt átírtam, így most IE 11 az emulált browser. A script hibák már elmentek.Amúgy nekem az az érzésem, hogy ez a WebBrowser control igazából legacy. Ami azért érdekes, mivel szerintem ilyenre sok esetben lehet szükség. Az Android erre kiváló példa: korábban ott is custom WebViewer volt, ami merőben más volt mint az általad böngészésre használt bármelyik webböngésző. Aztán ugye a WebKit alapú lett, amivel már gyakorlatilag bármelyik weboldal ugyanúgy működik, mintha a Chrome-ot használnád.
Az Androidos appok jelentős része használja 3rd party loginhoz. Pl. én se szívesen adom meg a Google accom adatait egy custom űrlapon, hanem teszem inkább a Google-nek, aki majd tájékoztatja a hívó weboldalt/applikációt arról, hogy sikerült-e a login, és amilyen adatokra neki szüksége van.
Nyilván egy ilyen embedded browserrel nem szörfölni akarok a neten, hanem ugyanilyen loginhoz akarom felhasználni. Ez szerintem fontos és nem hinném, hogy csak én hiányolom.
Most hogy megvan a cookie, már megy minden, a httpclientet simán felparaméterezem, még a user agentet is testre szabom. Cookie élettartam, stb. Ha a webbrowser is ugyanazt tudná, mint a httpclient (csak nyilván vizuális felülettel együtt), akkor nem lenne itt semmi gond.
-
martonx
veterán
-
Keem1
veterán
válasz
joysefke #9404 üzenetére
Ez így jól hangzik, de a "gond" az, hogy az SSO már készen van
A beléptetés egy adott oldalon megvan, nekem az ott utazó access tokenre van/volt szükségem. A toolom alapvetően konzol app lett volna, de mivel kell az access már egy belső sitehoz, muszáj volt átírnom, hisz konzolon nem tudnám magam beléptetni.Unalmas háttérsztori:
Egy k*va nagy amerikai cégnél dolgozom, és a sokszázezer munkavállalóból mi, az a csapat, ahol dolgozom, csak kis hal. Csak miattunk a developer csapat nem fog olyan toolokat fejleszteni, ami a munkánkat könnyebbé tenné, vagy legalábbis már rég nyugdíjas leszek, mire elkészülne. API nincs. Marad az, hogy megcsináljuk mi, akik ugyan nem programozók vagyunk, de azért konyítunk hozzá kicsit. Az SSO-nk, amivel a céges dolgokat elérjük, már adott. Többek között a cookieban van egy kb. 10 km hosszú access token, erre van szükségem, hogy a megfelelő oldalon a webclientet beléptessem, ami aztán eléri a szükséges adatokat a fél internetnyi méretű intraneten.Szóval nem azért adom itt a hülyét és jobbnál jobb feladatokban kérem a segítségeteket, hogy fárasszalak benneteket, hanem mert a munkám megkönnyítése érdekében jobban járok, ha megcsinálok bizonyos programokat, így bár idő és fáradság mire megszülöm (a ti segítségetekkel), de utána ismétlődő feladatok válnak könnyebbé. Pl. egy rohadt nagy, több 10 ezres adathalmazt egy weboldalról lementeni és valahogy excelbe varázsolni kézzel is lehetséges, de már kész a tool hozzá, ami végigparsolja az összes oldalt, és dob belőle egy excel táblát.
Unalmas sztori vége
-
joysefke
veterán
Azure AD?
szvsz ezeket a tutorialokat lenne érdemes megnézni.
Alapvetően úgy működik a SSO, hogy van egy Identity Platform (IP) (e.g. Azure AD, vagy valami egyéb) aki a user adatbázist és az azonosításhoz szükséges információkat tartalmazza. Ez az IP ismeri a te alkalmazásodat, az ott be van regisztálva: egyebek mellett pld az IP nyilvántart az alkalmazáshoz egy redirect url-t amivel sikeres user-bejelentkeztetés után Http-redirectelheti a browsert vissza az apphoz.Az IP ezen felül nyilvántartja hogy az adott appnak a domain/tenant admin mit engedélyezett mihez milyen erősorrásokhoz legyen milyen hozzáférése/ vagy egyáltalán mihez legyen lehetősége a usertől hozzáférést kérni (admin consent-user consent).
Amikor a user be akar a Web-appodon jelentkezni, akkor a Web-app őt átirányítja (http-redirect) az IP bejelentkeztető oldalára, a user bejelentkezik. Ha szükséges akkor bejelentkezé után az IP a webalkalmazás nevében engedélyt kér a usertől az előre definiált adatok elérésére, a user ezt leokézhatja. Ha az IP boldog a bejelentkeztetéssel, akkor generál egy (vagy több) tokent. Ha OpenIdConnect a használt protokol akkor elsősorban egy ID-token generálódik (és esetleg másegyebek). Ez az ID token belekerül a Http-responsba amit az IP küld vissza a browsernek, egy Http redirect keretében amivel a usert visszaküldi as bejelentkeztetést kezdeményező Web-apphoz.
A WebApp az ID token birtokában annak tartalmából ellenőrizni tudja a böngészőt felhasználó user identitását.
=======
AzureAD-ra ingyen tudsz regisztrálni (Azure AD tenantot/domaint készíteni) ezután fogod és kipróbálod a kód sampleket (próbáltam működnek ootb), ezután megérted az OpenIdConnect use caseket (azonosítod a sajátodat) aztán úgy haladsz tovább. Ez az elmélet
NET + ASP Net Core jól működő middleware komponsnseket tartalmaz ezekhez
-
Keem1
veterán
Voltaképp megoldottam, a WebBrowser built-in client képes rá, de sztem IE 6.0 alapokon nyugszik és egy modern page egyrészt fosul néz ki rajta, másrészt a rengeteg jQuery, Javascript dobálja a hibákat.
Pedig van a gépemen Edge is, meg lehetne válogatni böngészőmotort Chrome, Firefox közül is.Ezekre valakinek megoldás? Vagy másik engine dobja a login page-et, vagy valahoy letiltani a kb. 15 db JS hibát?
De a lényeg: bent vagyok SSO-val és megvan a token is.
-
Keem1
veterán
Srácok, szokásos céges tool...
Adott egy olyan access, ahol céges SSO-val kellene beloginolni, pl. mint amikor 3rd party site átdob a Google loginra. A dolgot úgy képzeltem el, hogy valamilyen, akár egy beépített, akár külső böngészővel behozni a login oldalt, ahol a user beloggol, majd ha sikerült a login, ebből kéne egy session ID-t elkapni a cookieban. Ezzel már menni fog az, amit voltaképp megvalósítanék (most is megy, de nagyo bénán, a Chrome dev toolsból kell kimásolni).Azt nem tudom, hogy induljak neki. Van valami beépített browser, használjak külsőt és számomra egyelőre ködös módon szedjem ki valahogy a tokent?
Lenne javaslatotok, merre kezdjem?
Mielőtt valaki céges biztonságot kritizálná, gyorsan hozzá kell tennem, hogy csak VPN-en megy, anélkül a login oldal 404-et dob.
-
fatal`
titán
válasz
DrojDtroll #9398 üzenetére
FormatException vagy ConfigurationErrorsException (ezt inkább hiányzó config paraméternél tenném, ha nem lehet értelmes defaultot adni)
Új hozzászólás Aktív témák
Hirdetés
● ha kódot szúrsz be, használd a PROGRAMKÓD formázási funkciót!
- Acer, notebook, laptop, Ryzen 5 5500u, 16gb ddr4, 1tb ssd, 15.6 col
- Eladó 3. generációs I7-es számítógép
- ASUS ROG STRIX 850W 80 PLUS Gold - Garancia 2033.05.04
- Új Lenovo 14 Ideapad 5 FHD IPS i5-1235U 4.4Ghz 10mag 16GB 512GB SSD Intel Iris XE Win11 Garancia
- AMD Ryzen 7 5800X3D 8-Core 3.4GHz - AQUA garancia 2026.04.20
- Laptop felvásárlás , egy darab, több darab, új , használt ! Korrekt áron !
- Motorola Moto G86 8/256 Cosmic Sky 1 év gari
- Új MSI Katana 15 Gamer FHD IPS 144Hz i7-13620H 10mag 16GB 512GB Nvidia RTX 4060 8GB Win11 Garancia
- Szinte új! 3 Hónapos! Playstation 5 Slim Disc (Lemezes) Kiadás! Garancia: 2027.05.15
- DELL Latitude 7340 i7-1365U 16GB 512GB 13.3" FHD+ TouchScren 1 év garancia
Állásajánlatok
Cég: FOTC
Város: Budapest