Category Archives: Development

YAML Pipelines – Azure DevOps [Jiří Kanda, Vzdělávací okénko, 27.3.2025]

V tomto videu se dozvíte vše o našich nových YAML pipelines v Azure DevOps, které prezentuje Jiří Kanda. Jirka vysvětluje, proč jsme se rozhodli přejít na YAML pipelines a jaké výhody nám to přináší.

  • Specifika našich buildů a důvody pro změnu na YAML pipelines.
  • Výhody YAML pipelines, jako jsou lepší parametrizace a paralelizace.
  • Základní syntaxe YAML a struktura YAML pipelines.
  • Paralelní běh jobů a použití více agentů.
  • Volitelné parametry buildů a task scheduler.
  • Podpora pro integrační testy a automatické pull requesty.
  • Použití deduplication a reprodukovatelnost buildů.
  • Validace zranitelností nuget balíčků a definice pipeline v projektech.
  • Problémy s manuálním spuštěním buildů.

Záznam ze Vzdělávacího okénka HAVIT z 27. března 2025.

await foo?.DoAsync() [Vzdělávací okénko, 20.3.2025]

Krátce o pasti zápisu await foo?.DoAsync(), kdy použití null-conditional accessu vede na await null a NullReferenceException.

Blazor ValueExpression binding a validace – záznam [Vzdělávací okénko, 13.3.2025]

Tentokrát o ValueExpression parametrech v Blazoru a potřebě jejich správného použití pro fungování validací.

Záznam ze Vzdělávacího okénka HAVIT z 13. března 2025. Zkoušíme zpestřit novým formátem mini-okének, kde se budou objevovat ad-hoc témata v řádu 2-10 minut.

Novinky v .NET 9 a výhled na .NET 10 – záznam a slides [Robert Haken, WUG Dev Day, 28.2.2025]

Záznam ze Vzdělávacího okénka HAVIT z 28. února 2025, kde jsem telegraficky představoval novinky z „.NET 9 vlny“ a přicházející v „.NET 10 vlně“.

Slides

I[Async]Enumerable [Jiří Kanda, Vzdělávací okénko, 31.10.2024]

Záznam ze Vzdělávacího okénka HAVIT z 31. října 2024, kde Jiří Kanda povídal o IEnumerable interface a jeho asynchronní verzi IAsyncEnumerable.

Azure Entra ID – Conditional Access Policies [Dan Hrubý, HAVIT Vzdělávací okénko, 26.9.2024]

Záznam ze Vzdělávacího okénka HAVIT z 26. září 2024, kde Daniel Hrubý povídal o Microsoft Azure Entra ID a aspektech jako MFA, Conditional Access Policies, B2B Collaboration atp.

[Blazor] await periodicTimer.WaitForNextTickAsync() – dobrý sluha, ale špatný pán

Pozor na await periodicTimer.WaitForNextTickAsync(). Tato metoda láká svojí asynchronní signaturou k pohodlnému uspořádání periodických úloha a zejména v Blazoru vás tak může zlákat k implementaci aktualizací UI:

protected override async Task OnInitializedAsync()
{
    await StartTimerAsync();
}

private async Task StartTimerAsync()
{
    using var timer = new PeriodicTimer(TimeSpan.FromSeconds(10));
    while (await timer.WaitForNextTickAsync())
    {
        // do some UI updates here
    }
}

POZOR! Takovéto uspořádání sice neblokuje UI thread a díky async-await to jede dál, problém je však v tom, že metoda, z které se takovýto kód volá, nikdy neskončí.

Pokud tedy například takovýto StartTimeAsync() přímo zavolám z OnIntializeAsync/OnParametersSetAsync/OnAfterRenderAsync/action-callbacku, pak tato parent-metoda nikdy neskončí a může to mít dost nečekané následky. Například:

  • pokud to zavolám z HxButton.OnClick obsluhy tlačítka, zůstane mi tam viset spinner, který nikdy neskončí,
    • tlačítko navíc zůstane pod single-click-protection, disabled, nepoužitelné,
  • pokud to zavolám z override OnInitializedAsync(), nedojde v prvním roundtripu k zavolání OnParametersSet[Async]() a dokud nepřijde další roundtrip, tak se mi OnParametersSet[Async]() neprovedou,
  • pokud to zavolám z override OnParametersSetAsync(), zůstává mi viset nedokončený Task v ComponentBase.CallStateHasChangedOnAsyncCompletion(), navíc musím ošetřit, že se OnParametersSetAsync() volá opakovaně a nechci si timerů pustit více,
  • pokud to zavolám z override OnAfterRenderAsync(bool firstRender), mohu si tím zablokovat volání await base.OnAfterRenderAsync(firstRender), což mi může narušit funkčnost definovanou předkem při dědění (zejména pro firstRender = true, které se provádí jen jednou)

PeriodicTimer.WaitForNextTickAsync() se tedy hodí do scénářů, kdy je zaručeno, že volající kód nikam nepokračuje a mohu se na příslušném místě točit „do nekonečna“ (např. jsem v metodě Main a točím nějakou cyklickou úlohu v konzolové aplikaci, nebo jsem v BackgroundService.ExecuteAsync()). Obecně však je potřeba dovolit dokončení volající metody a tedy pro spouštění použít tradiční uspořádání s Task.Run(..), kdy umístíme timer (může to být i klasický Timer, asynchronní metoda WaitForNextTickAsync() zde již nehraje tak velkou roli) na ThreadPool a neawaitujeme v aktuální metodě jeho dokončení (fire & forget). V případě Blazoru si v takovém případě musíme ručně volat StateHasChanged(), popř. DispatchExceptionAsync().

public MyComponent : IDisposable
{
	private PeriodicTimer timer;

	protected override async Task OnInitializedAsync()
	{
		_ = Task.Run(StartTimerAsync);
	}

	private async Task StartTimerAsync()
	{
		timer = new PeriodicTimer(TimeSpan.FromSeconds(10));
		while (await timer.WaitForNextTickAsync())
		{
			// do some UI updates here
			StateHasChanged(); // as needed
		}
	}

	public void Dispose()
	{
		timer?.Dispose();
	}
}

Nesmíme samozřejmě zapomenout na úklid – timer.Dispose(), jinak nám Timer zůstane běžet i po zániku komponenty, vzniká resource-leak atd.

Viz též ASP.NET Core Blazor dokumentace:

Blazored.FluentValidations issue [Robert Haken, HAVIT Vzdělávací okénko. 24.10.2024]

Záznam ze Vzdělávacího okénka HAVIT ze 24. října 2024, kde jsem ukazoval problematické chování Blazored.FluentValidationsValidator při komplexním view-modelu a validaci fieldů na sub-modelech.

https://github.com/Blazored/FluentValidation/issues/235

Go to file member (Visual Studio)

Dlouho mě trápilo, jak se ve větším souboru rychle donavigovat na membera, jehož jméno znám.

Resharper/Rider mají přímo Go to file member Alt+ \.

Visual Studio 2022 má Go to member, který má ale výchozí scope na Current solution.

Je to takový ten klasický Go to… s prefixem m:, který prostě prohledává member, ale v celé solution, ani to nedává výsledky aktuálního souboru na první místo 😭. Chybí tam jakákoliv klávesová zkratka, nebo cesta, která by to otevřela předscopované na Current file.

OVŠEM!!! Má to ovšem jednu pro mě až dnes objevenou vlastnost, která to činí použitelným (pro mě) – pamatuje si to poslední scope, a to samostatně pro jednotlivé use-case. Má to navíc stejnou klávesovou zkratku Alt + \.

Takže:

Jednou to otevřete přes Go to member (Alt+\) a změníte si scope na Current file a napříště to tam zůstane zapamatováno.

Neovlivní to však ostatní use-case. Pro Go to all (Ctrl + T) nebo Go to file (Ctrl + Shift +T) si to u mě dále pamatuje scope Current solution.

Quality of live changer! 🤣🥳

.NET Memory Internals – záznam a slides [Robert Haken, WUG Days Brno, 6.9.2024]

Záznam ze Vzdělávacího okénka HAVIT z 6. září 2024, kde jsem ukazovat základy uspořádání paměti v .NET.

Slides