ASP.NET Core Razor bileşen yaşam döngüsü
Uyarı
ASP.NET Core'un bu sürümü artık desteklenmiyor. Daha fazla bilgi için bkz . .NET ve .NET Core Destek İlkesi. Geçerli sürüm için bu makalenin .NET 8 sürümüne bakın.
Bu makalede, ASP.NET Temel Razor bileşen yaşam döngüsü ve yaşam döngüsü olaylarının nasıl kullanılacağı açıklanmaktadır.
Yaşam döngüsü olayları
Bileşen, Razor bileşen yaşam döngüsü olaylarını Razor bir dizi zaman uyumlu ve zaman uyumsuz yaşam döngüsü yönteminde işler. Bileşen başlatma ve işleme sırasında bileşenlerde ek işlemler gerçekleştirmek için yaşam döngüsü yöntemleri geçersiz kılınabilir.
Bu makale, karmaşık çerçeve mantığını netleştirmek için bileşen yaşam döngüsü olay işlemeyi basitleştirir ve yıllar içinde yapılan her değişikliği kapsamaz. Özel olay işlemeyi ComponentBase
yaşam döngüsü olay işleme ile Blazortümleştirmek için başvuru kaynağına erişmeniz gerekebilir. Başvuru kaynağındaki kod açıklamaları, bu makalede veya API belgelerinde görünmeyen yaşam döngüsü olay işleme hakkında ek açıklamalar içerir.
Not
.NET başvuru kaynağına yönelik belge bağlantıları genellikle deponun varsayılan dalını yükler ve bu dal .NET'in sonraki sürümü için geçerli geliştirmeyi temsil eder. Belirli bir sürümün etiketini seçmek için Dalları veya etiketleri değiştir açılan listesini kullanın. Daha fazla bilgi için bkz. ASP.NET Core kaynak kodunun sürüm etiketini seçme (dotnet/AspNetCore.Docs #26205).
Aşağıdaki basitleştirilmiş diyagramlarda bileşen yaşam döngüsü olay işleme gösterilmektedir Razor . Yaşam döngüsü olaylarıyla ilişkili C# yöntemleri, bu makalenin aşağıdaki bölümlerindeki örneklerle tanımlanır.
Bileşen yaşam döngüsü olayları:
- Bileşen bir istekte ilk kez işleniyorsa:
- Bileşenin örneğini oluşturun.
- Özellik ekleme işlemi gerçekleştirin.
OnInitialized{Async}
çağrısı yapın. Tamamlanmamış Task bir döndürülürse, Task öğesini bekler ve ardından bileşen yeniden oluşturulur. Zaman uyumlu yöntem, zaman uyumsuz yöntemden önce çağrılır.
OnParametersSet{Async}
çağrısı yapın. Tamamlanmamış Task bir döndürülürse, Task öğesini bekler ve ardından bileşen yeniden oluşturulur. Zaman uyumlu yöntem, zaman uyumsuz yöntemden önce çağrılır.- Tüm zaman uyumlu işler ve tamamlamalar Taskiçin işleyin.
Not
Bir bileşen işlenmeden önce yaşam döngüsü olaylarında gerçekleştirilen zaman uyumsuz eylemler tamamlanmayabilir. Daha fazla bilgi için bu makalenin devamında İşlemede tamamlanmamış zaman uyumsuz eylemleri işleme bölümüne bakın.
Hangi alt bileşenlerin mevcut olduğunu belirleyen işleme olduğundan, bir üst bileşen alt bileşenlerden önce işlenir. Zaman uyumlu üst bileşen başlatma kullanılırsa, önce üst başlatmanın tamamlanması garanti edilir. Zaman uyumsuz üst bileşen başlatma kullanılırsa, çalışan başlatma koduna bağlı olduğundan üst ve alt bileşen başlatmanın tamamlanma sırası belirlenemez.
DOM olay işleme:
- Olay işleyicisi çalıştırılır.
- Tamamlanmamış Task bir döndürülürse, Task öğesini bekler ve ardından bileşen yeniden oluşturulur.
- Tüm zaman uyumlu işler ve tamamlamalar Taskiçin işleyin.
Yaşam Render
döngüsü:
- Aşağıdaki koşulların her ikisi de karşılandığında bileşen üzerinde daha fazla işleme işlemi yapmaktan kaçının:
- bu ilk işleme değildir.
ShouldRender
döndürürfalse
.
- İşleme ağacı farkını (fark) oluşturun ve bileşeni işleyin.
- DOM'un güncelleştirilecek olmasını bekle.
OnAfterRender{Async}
çağrısı yapın. Zaman uyumlu yöntem, zaman uyumsuz yöntemden önce çağrılır.
Geliştirici, bir rerender ile sonuçlanır StateHasChanged
çağrısında bulunur. Daha fazla bilgi için bkz. ASP.NET Core Razor bileşenini işleme.
Parametreler ayarlandığında (SetParametersAsync
)
SetParametersAsync , bileşenin üst öğesi tarafından işleme ağacında veya yol parametrelerinden sağlanan parametreleri ayarlar.
Yöntemin ParameterView parametresi, her çağrılışında SetParametersAsync bileşen için bileşen parametre değerleri kümesini içerir. Geliştirici kodu, yöntemini geçersiz kılarak SetParametersAsync doğrudan 'nin parametreleriyle ParameterViewetkileşimde bulunabilir.
varsayılan uygulamasıSetParametersAsync, içinde karşılık gelen bir değere sahip olan veya[CascadingParameter]
özniteliğiyle [Parameter]
her özelliğin ParameterViewdeğerini ayarlar. içinde ParameterView karşılık gelen bir değere sahip olmayan parametreler değişmeden bırakılır.
Genellikle, kodunuz geçersiz kılma SetParametersAsyncsırasında temel sınıf yöntemini (await base.SetParametersAsync(parameters);
) çağırmalıdır. Gelişmiş senaryolarda geliştirici kodu, temel sınıf yöntemini çağırmayarak gelen parametrelerin değerlerini herhangi bir şekilde yorumlayabilir. Örneğin, gelen parametreleri sınıfın özelliklerine atama gereksinimi yoktur. Ancak, temel sınıf yöntemini çağırmadan kodunuzu yapılandırırken başvuru kaynağına başvurmanız ComponentBase
gerekir çünkü diğer yaşam döngüsü yöntemlerini çağırır ve karmaşık bir şekilde işlemeyi tetikler.
Not
.NET başvuru kaynağına yönelik belge bağlantıları genellikle deponun varsayılan dalını yükler ve bu dal .NET'in sonraki sürümü için geçerli geliştirmeyi temsil eder. Belirli bir sürümün etiketini seçmek için Dalları veya etiketleri değiştir açılan listesini kullanın. Daha fazla bilgi için bkz. ASP.NET Core kaynak kodunun sürüm etiketini seçme (dotnet/AspNetCore.Docs #26205).
Gelen parametrelerin başlatma ve işleme mantığına ComponentBase.SetParametersAsync güvenmek ancak işlememek istiyorsanız, temel sınıf yöntemine boş ParameterView bir geçirme seçeneğiniz vardır:
await base.SetParametersAsync(ParameterView.Empty);
Geliştirici kodunda olay işleyicileri sağlanıyorsa, bunları elden çıkarıldığında çıkarın. Daha fazla bilgi için ve IAsyncDisposable
ile IDisposable
bileşen elden çıkarma bölümüne bakın.
Aşağıdaki örnekte, ParameterView.TryGetValue bir yol parametresinin Param
ayrıştırılması başarılı olursa parametresinin Param
değerini value
atar. olmadığında value
null
, değer bileşen tarafından görüntülenir.
Yol parametresi eşleştirme büyük/küçük harfe duyarsız olsa da, TryGetValue yalnızca yol şablonundaki büyük/küçük harfe duyarlı parametre adlarını eşleştirir. Aşağıdaki örnek, değerini değil ile TryGetValue/{param?}
almak için yol şablonunda öğesinin kullanılmasını /{Param?}
gerektirir. Bu senaryoda kullanılıyorsa /{param?}
, TryGetValue döndürür false
ve message
iki dizeye de message
ayarlanmadı.
SetParamsAsync.razor
:
@page "/set-params-async/{Param?}"
<PageTitle>Set Parameters Async</PageTitle>
<h1>Set Parameters Async Example</h1>
<p>@message</p>
@code {
private string message = "Not set";
[Parameter]
public string? Param { get; set; }
public override async Task SetParametersAsync(ParameterView parameters)
{
if (parameters.TryGetValue<string>(nameof(Param), out var value))
{
if (value is null)
{
message = "The value of 'Param' is null.";
}
else
{
message = $"The value of 'Param' is {value}.";
}
}
await base.SetParametersAsync(parameters);
}
}
@page "/set-params-async/{Param?}"
<PageTitle>Set Parameters Async</PageTitle>
<h1>Set Parameters Async Example</h1>
<p>@message</p>
@code {
private string message = "Not set";
[Parameter]
public string? Param { get; set; }
public override async Task SetParametersAsync(ParameterView parameters)
{
if (parameters.TryGetValue<string>(nameof(Param), out var value))
{
if (value is null)
{
message = "The value of 'Param' is null.";
}
else
{
message = $"The value of 'Param' is {value}.";
}
}
await base.SetParametersAsync(parameters);
}
}
@page "/set-params-async/{Param?}"
<p>@message</p>
@code {
private string message = "Not set";
[Parameter]
public string? Param { get; set; }
public override async Task SetParametersAsync(ParameterView parameters)
{
if (parameters.TryGetValue<string>(nameof(Param), out var value))
{
if (value is null)
{
message = "The value of 'Param' is null.";
}
else
{
message = $"The value of 'Param' is {value}.";
}
}
await base.SetParametersAsync(parameters);
}
}
@page "/set-params-async/{Param?}"
<p>@message</p>
@code {
private string message = "Not set";
[Parameter]
public string? Param { get; set; }
public override async Task SetParametersAsync(ParameterView parameters)
{
if (parameters.TryGetValue<string>(nameof(Param), out var value))
{
if (value is null)
{
message = "The value of 'Param' is null.";
}
else
{
message = $"The value of 'Param' is {value}.";
}
}
await base.SetParametersAsync(parameters);
}
}
@page "/set-params-async/{Param?}"
<p>@message</p>
@code {
private string message = "Not set";
[Parameter]
public string Param { get; set; }
public override async Task SetParametersAsync(ParameterView parameters)
{
if (parameters.TryGetValue<string>(nameof(Param), out var value))
{
if (value is null)
{
message = "The value of 'Param' is null.";
}
else
{
message = $"The value of 'Param' is {value}.";
}
}
await base.SetParametersAsync(parameters);
}
}
@page "/set-params-async"
@page "/set-params-async/{Param}"
<p>@message</p>
@code {
private string message = "Not set";
[Parameter]
public string Param { get; set; }
public override async Task SetParametersAsync(ParameterView parameters)
{
if (parameters.TryGetValue<string>(nameof(Param), out var value))
{
if (value is null)
{
message = "The value of 'Param' is null.";
}
else
{
message = $"The value of 'Param' is {value}.";
}
}
await base.SetParametersAsync(parameters);
}
}
Bileşen başlatma (OnInitialized{Async}
)
OnInitialized ve OnInitializedAsync yalnızca bileşen örneğinin tüm ömrü boyunca bir bileşeni başlatmak için kullanılır. Parametre değerleri ve parametre değeri değişiklikleri, bu yöntemlerde gerçekleştirilen başlatmayı etkilememelidir. Örneğin, statik seçenekleri bileşenin ömrü boyunca değişmeyen ve parametre değerlerine bağımlı olmayan bir açılan listeye yükleme işlemi bu yaşam döngüsü yöntemlerinden birinde gerçekleştirilir. Parametre değerleri veya parametre değerlerindeki değişiklikler bileşen durumunu etkiliyorsa, bunun yerine kullanın OnParametersSet{Async}
.
Bu yöntemler, içinde ilk parametrelerini aldıktan sonra bileşen başlatıldığında çağrılır SetParametersAsync. Zaman uyumlu yöntem, zaman uyumsuz yöntemden önce çağrılır.
Zaman uyumlu üst bileşen başlatma kullanılırsa, alt bileşen başlatmadan önce üst başlatmanın tamamlanması garanti edilir. Zaman uyumsuz üst bileşen başlatma kullanılırsa, çalışan başlatma koduna bağlı olduğundan üst ve alt bileşen başlatmanın tamamlanma sırası belirlenemez.
Zaman uyumlu bir işlem için öğesini geçersiz kılın OnInitialized:
OnInit.razor
:
@page "/on-init"
<PageTitle>On Initialized</PageTitle>
<h1>On Initialized Example</h1>
<p>@message</p>
@code {
private string? message;
protected override void OnInitialized() =>
message = $"Initialized at {DateTime.Now}";
}
@page "/on-init"
<PageTitle>On Initialized</PageTitle>
<h1>On Initialized Example</h1>
<p>@message</p>
@code {
private string? message;
protected override void OnInitialized() =>
message = $"Initialized at {DateTime.Now}";
}
@page "/on-init"
<p>@message</p>
@code {
private string? message;
protected override void OnInitialized()
{
message = $"Initialized at {DateTime.Now}";
}
}
@page "/on-init"
<p>@message</p>
@code {
private string? message;
protected override void OnInitialized()
{
message = $"Initialized at {DateTime.Now}";
}
}
@page "/on-init"
<p>@message</p>
@code {
private string message;
protected override void OnInitialized()
{
message = $"Initialized at {DateTime.Now}";
}
}
@page "/on-init"
<p>@message</p>
@code {
private string message;
protected override void OnInitialized()
{
message = $"Initialized at {DateTime.Now}";
}
}
Zaman uyumsuz bir işlem gerçekleştirmek için geçersiz kılın OnInitializedAsync ve işlecini await
kullanın:
protected override async Task OnInitializedAsync()
{
await ...
}
Özel bir temel sınıf özel başlatma mantığıyla kullanılıyorsa, temel sınıfı çağırınOnInitializedAsync:
protected override async Task OnInitializedAsync()
{
await ...
await base.OnInitializedAsync();
}
Özel bir temel sınıf özel mantıkla kullanılmadığı sürece çağrı ComponentBase.OnInitializedAsync yapılması gerekmez. Daha fazla bilgi için Temel sınıf yaşam döngüsü yöntemleri bölümüne bakın.
Blazorsunucudaki içeriklerini önceden oluşturan uygulamalar iki kez arar OnInitializedAsync :
- Bileşen başlangıçta sayfanın bir parçası olarak statik olarak işlendiğinde.
- Tarayıcı bileşeni işlerken ikinci kez.
'de OnInitializedAsync geliştirici kodunun ön kayıt sırasında iki kez çalışmasını önlemek için, Ön kayıttan sonra durum bilgisi olan yeniden bağlanma bölümüne bakın. Bölümdeki içerik, s ve durum bilgisi olan SignalRyeniden bağlanmaya odaklanırBlazor Web App. Ön kayıt sırasında başlatma kodunun yürütülmesi sırasında durumu korumak için bkz . Prerender ASP.NET Core Razor bileşenleri.
'de OnInitializedAsync geliştirici kodunun ön kayıt sırasında iki kez çalışmasını önlemek için, Ön kayıttan sonra durum bilgisi olan yeniden bağlanma bölümüne bakın. Bölümdeki içerik ve durum bilgisi olanSignalR yeniden bağlanmaya odaklansa Blazor Server da, barındırılan Blazor WebAssembly çözümlerde (WebAssemblyPrerendered) ön kayıt senaryosu, geliştirici kodunun iki kez yürütülmesini önlemeye yönelik benzer koşullar ve yaklaşımlar içerir. Hazırlama sırasında başlatma kodunun yürütülmesi sırasında durumu korumak için bkz . Prerender ve ASP.NET Core Razor bileşenlerini tümleştirme.
Bir Blazor uygulama önceden çalıştırılırken JavaScript'e çağırma (JS birlikte çalışma) gibi bazı eylemler mümkün değildir. Bileşenlerin önceden girildiğinde farklı şekilde işlenmesi gerekebilir. Daha fazla bilgi için JavaScript birlikte çalışma ile ön giriş yapma bölümüne bakın.
Geliştirici kodunda olay işleyicileri sağlanıyorsa, bunları elden çıkarıldığında çıkarın. Daha fazla bilgi için Bileşen atma ve IDisposable
IAsyncDisposable
atma bölümüne bakın.
'de uzun süre çalışan zaman uyumsuz görevleri OnInitializedAsync tam olarak işlemek üzere gerçekleştiren bileşenler için kullanıcı deneyimini geliştirmek için statik sunucu tarafı işleme (statik SSR) veya ön işlem ile akış işlemeyi kullanın. Daha fazla bilgi için bkz. ASP.NET Core Razor bileşenini işleme.
Parametreler ayarlandıktan sonra (OnParametersSet{Async}
)
OnParametersSet veya OnParametersSetAsync çağrılır:
bileşen veya OnInitializedAsynciçinde OnInitialized başlatıldıktan sonra.
Üst bileşen yeniden başlatıldığında ve sağladığında:
- En az bir parametre değiştiğinde bilinen veya ilkel sabit türler.
- Karmaşık türemiş parametreler. Çerçeve, karmaşık türdeki bir parametrenin değerlerinin dahili olarak sessize alınıp alınmadığını bilemez, bu nedenle çerçeve her zaman bir veya daha fazla karmaşık türe sahip parametre mevcut olduğunda parametre kümesini değiştirilmiş olarak değerlendirir.
İşleme kuralları hakkında daha fazla bilgi için bkz . ASP.NET Core Razor bileşeni işleme.
Zaman uyumlu yöntem, zaman uyumsuz yöntemden önce çağrılır.
Parametre değerleri değişmemiş olsa bile yöntemler çağrılabilir. Bu davranış, geliştiricilerin bu parametrelere bağımlı verileri veya durumu yeniden başlatmadan önce parametre değerlerinin gerçekten değişip değişmediğini denetlemek için yöntemler içinde ek mantık uygulama gereksiniminin altını çizer.
Aşağıdaki örnek bileşen için, url'deki bileşenin sayfasına gidin:
- tarafından alınan bir başlangıç tarihiyle
StartDate
:/on-parameters-set/2021-03-19
- Başlangıç tarihi olmadan, burada
StartDate
geçerli yerel saatin bir değeri atanır:/on-parameters-set
Not
Bileşen yolunda, bir parametreyi yol kısıtlaması datetime
ile kısıtlamak DateTime ve parametreyi isteğe bağlı hale getirmek mümkün değildir. Bu nedenle, aşağıdaki OnParamsSet
bileşen URL'de sağlanan bir tarih kesimi ile ve olmadan yönlendirmeyi işlemek için iki @page
yönerge kullanır.
OnParamsSet.razor
:
@page "/on-params-set"
@page "/on-params-set/{StartDate:datetime}"
<PageTitle>On Parameters Set</PageTitle>
<h1>On Parameters Set Example</h1>
<p>
Pass a datetime in the URI of the browser's address bar.
For example, add <code>/1-1-2024</code> to the address.
</p>
<p>@message</p>
@code {
private string? message;
[Parameter]
public DateTime StartDate { get; set; }
protected override void OnParametersSet()
{
if (StartDate == default)
{
StartDate = DateTime.Now;
message = $"No start date in URL. Default value applied " +
$"(StartDate: {StartDate}).";
}
else
{
message = $"The start date in the URL was used " +
$"(StartDate: {StartDate}).";
}
}
}
@page "/on-params-set"
@page "/on-params-set/{StartDate:datetime}"
<PageTitle>On Parameters Set</PageTitle>
<h1>On Parameters Set Example</h1>
<p>
Pass a datetime in the URI of the browser's address bar.
For example, add <code>/1-1-2024</code> to the address.
</p>
<p>@message</p>
@code {
private string? message;
[Parameter]
public DateTime StartDate { get; set; }
protected override void OnParametersSet()
{
if (StartDate == default)
{
StartDate = DateTime.Now;
message = $"No start date in URL. Default value applied " +
$"(StartDate: {StartDate}).";
}
else
{
message = $"The start date in the URL was used " +
$"(StartDate: {StartDate}).";
}
}
}
@page "/on-params-set"
@page "/on-params-set/{StartDate:datetime}"
<p>@message</p>
@code {
private string? message;
[Parameter]
public DateTime StartDate { get; set; }
protected override void OnParametersSet()
{
if (StartDate == default)
{
StartDate = DateTime.Now;
message = $"No start date in URL. Default value applied (StartDate: {StartDate}).";
}
else
{
message = $"The start date in the URL was used (StartDate: {StartDate}).";
}
}
}
@page "/on-params-set"
@page "/on-params-set/{StartDate:datetime}"
<p>@message</p>
@code {
private string? message;
[Parameter]
public DateTime StartDate { get; set; }
protected override void OnParametersSet()
{
if (StartDate == default)
{
StartDate = DateTime.Now;
message = $"No start date in URL. Default value applied (StartDate: {StartDate}).";
}
else
{
message = $"The start date in the URL was used (StartDate: {StartDate}).";
}
}
}
@page "/on-params-set"
@page "/on-params-set/{StartDate:datetime}"
<p>@message</p>
@code {
private string message;
[Parameter]
public DateTime StartDate { get; set; }
protected override void OnParametersSet()
{
if (StartDate == default)
{
StartDate = DateTime.Now;
message = $"No start date in URL. Default value applied (StartDate: {StartDate}).";
}
else
{
message = $"The start date in the URL was used (StartDate: {StartDate}).";
}
}
}
@page "/on-params-set"
@page "/on-params-set/{StartDate:datetime}"
<p>@message</p>
@code {
private string message;
[Parameter]
public DateTime StartDate { get; set; }
protected override void OnParametersSet()
{
if (StartDate == default)
{
StartDate = DateTime.Now;
message = $"No start date in URL. Default value applied (StartDate: {StartDate}).";
}
else
{
message = $"The start date in the URL was used (StartDate: {StartDate}).";
}
}
}
Parametreleri ve özellik değerlerini uygularken zaman uyumsuz çalışma yaşam döngüsü olayı sırasında OnParametersSetAsync gerçekleşmelidir:
protected override async Task OnParametersSetAsync()
{
await ...
}
Özel bir temel sınıf özel başlatma mantığıyla kullanılıyorsa, temel sınıfı çağırınOnParametersSetAsync:
protected override async Task OnParametersSetAsync()
{
await ...
await base.OnParametersSetAsync();
}
Özel bir temel sınıf özel mantıkla kullanılmadığı sürece çağrı ComponentBase.OnParametersSetAsync yapılması gerekmez. Daha fazla bilgi için Temel sınıf yaşam döngüsü yöntemleri bölümüne bakın.
Geliştirici kodunda olay işleyicileri sağlanıyorsa, bunları elden çıkarıldığında çıkarın. Daha fazla bilgi için Bileşen atma ve IDisposable
IAsyncDisposable
atma bölümüne bakın.
Yol parametreleri ve kısıtlamaları hakkında daha fazla bilgi için bkz . ASP.NET Çekirdek Blazor yönlendirme ve gezinti.
Bazı senaryolarda performansı geliştirmek için el ile uygulama SetParametersAsync
örneği için bkz . ASP.NET Temel Blazor performans en iyi yöntemleri.
Bileşen işlendikten sonra (OnAfterRender{Async}
)
OnAfterRender ve OnAfterRenderAsync bir bileşen etkileşimli olarak işlendikten ve kullanıcı arabirimi güncelleştirmeyi tamamladıktan sonra (örneğin, tarayıcı DOM'sine öğeler eklendikten sonra) çağrılır. Öğe ve bileşen başvuruları bu noktada doldurulur. İşlenen dom öğeleriyle etkileşim kuran birlikte çalışma çağrıları gibi JS işlenen içerikle ek başlatma adımları gerçekleştirmek için bu aşamayı kullanın. Zaman uyumlu yöntem, zaman uyumsuz yöntemden önce çağrılır.
Bu işlemler bir canlı tarayıcı DOM'sine bağlı olmadığından ve DOM güncelleştirilmeden önce zaten tamamlandığından, bu yöntemler sunucuda ön kayıt veya statik sunucu tarafı işleme (statik SSR) sırasında çağrılamaz.
için OnAfterRenderAsync, sonsuz bir işleme döngüsünden kaçınmak için döndürülen Task
herhangi bir öğe tamamlandıktan sonra bileşen otomatik olarak yeniden oluşturulmaz.
OnAfterRender ve OnAfterRenderAsync bir bileşenin işlenmesi tamamlandıktan sonra çağrılır. Öğe ve bileşen başvuruları bu noktada doldurulur. İşlenen dom öğeleriyle etkileşim kuran birlikte çalışma çağrıları gibi JS işlenen içerikle ek başlatma adımları gerçekleştirmek için bu aşamayı kullanın. Zaman uyumlu yöntem, zaman uyumsuz yöntemden önce çağrılır.
Bu yöntemler, canlı tarayıcı DOM'sine eklenmediğinden ve DOM güncelleştirilmeden önce zaten tamamlandığından, ön kayıt sırasında çağrılamaz.
için OnAfterRenderAsync, sonsuz bir işleme döngüsünden kaçınmak için döndürülen Task
herhangi bir öğe tamamlandıktan sonra bileşen otomatik olarak yeniden oluşturulmaz.
firstRender
ve OnAfterRenderAsyncparametresiOnAfterRender:
- Bileşen örneğinin ilk işlenme zamanına ayarlanır
true
. - Başlatma işinin yalnızca bir kez gerçekleştirildiğinden emin olmak için kullanılabilir.
AfterRender.razor
:
@page "/after-render"
@inject ILogger<AfterRender> Logger
<PageTitle>After Render</PageTitle>
<h1>After Render Example</h1>
<p>
<button @onclick="HandleClick">Log information (and trigger a render)</button>
</p>
<p>Study logged messages in the console.</p>
@code {
protected override void OnAfterRender(bool firstRender) =>
Logger.LogInformation("firstRender = {FirstRender}", firstRender);
private void HandleClick() => Logger.LogInformation("HandleClick called");
}
@page "/after-render"
@inject ILogger<AfterRender> Logger
<PageTitle>After Render</PageTitle>
<h1>After Render Example</h1>
<p>
<button @onclick="HandleClick">Log information (and trigger a render)</button>
</p>
<p>Study logged messages in the console.</p>
@code {
protected override void OnAfterRender(bool firstRender) =>
Logger.LogInformation("firstRender = {FirstRender}", firstRender);
private void HandleClick() => Logger.LogInformation("HandleClick called");
}
@page "/after-render"
@inject ILogger<AfterRender> Logger
<PageTitle>After Render</PageTitle>
<h1>After Render Example</h1>
<p>
<button @onclick="HandleClick">Log information (and trigger a render)</button>
</p>
<p>Study logged messages in the console.</p>
@code {
protected override void OnAfterRender(bool firstRender)
{
Logger.LogInformation("OnAfterRender: firstRender = {FirstRender}", firstRender);
}
private void HandleClick()
{
Logger.LogInformation("HandleClick called");
}
}
@page "/after-render"
@inject ILogger<AfterRender> Logger
<PageTitle>After Render</PageTitle>
<h1>After Render Example</h1>
<p>
<button @onclick="HandleClick">Log information (and trigger a render)</button>
</p>
<p>Study logged messages in the console.</p>
@code {
protected override void OnAfterRender(bool firstRender)
{
Logger.LogInformation("OnAfterRender: firstRender = {FirstRender}", firstRender);
}
private void HandleClick()
{
Logger.LogInformation("HandleClick called");
}
}
@page "/after-render"
@using Microsoft.Extensions.Logging
@inject ILogger<AfterRender> Logger
<h1>After Render Example</h1>
<p>
<button @onclick="HandleClick">Log information (and trigger a render)</button>
</p>
<p>Study logged messages in the console.</p>
@code {
protected override void OnAfterRender(bool firstRender)
{
Logger.LogInformation("OnAfterRender: firstRender = {FirstRender}", firstRender);
}
private void HandleClick()
{
Logger.LogInformation("HandleClick called");
}
}
@page "/after-render"
@using Microsoft.Extensions.Logging
@inject ILogger<AfterRender> Logger
<h1>After Render Example</h1>
<p>
<button @onclick="HandleClick">Log information (and trigger a render)</button>
</p>
<p>Study logged messages in the console.</p>
@code {
protected override void OnAfterRender(bool firstRender)
{
Logger.LogInformation("OnAfterRender: firstRender = {FirstRender}", firstRender);
}
private void HandleClick()
{
Logger.LogInformation("HandleClick called");
}
}
Örnek, AfterRender.razor
sayfa yüklendiğinde ve düğme seçildiğinde konsola aşağıdaki çıkışı oluşturur:
OnAfterRender: firstRender = True
HandleClick called
OnAfterRender: firstRender = False
İşlemeden hemen sonra zaman uyumsuz çalışma yaşam döngüsü olayı sırasında OnAfterRenderAsync gerçekleşmelidir:
protected override async Task OnAfterRenderAsync(bool firstRender)
{
...
}
Özel bir temel sınıf özel başlatma mantığıyla kullanılıyorsa, temel sınıfı çağırınOnAfterRenderAsync:
protected override async Task OnAfterRenderAsync(bool firstRender)
{
...
await base.OnAfterRenderAsync(firstRender);
}
Özel bir temel sınıf özel mantıkla kullanılmadığı sürece çağrı ComponentBase.OnAfterRenderAsync yapılması gerekmez. Daha fazla bilgi için Temel sınıf yaşam döngüsü yöntemleri bölümüne bakın.
'den OnAfterRenderAsyncdöndürseniz Task bile, görev tamamlandıktan sonra çerçeve bileşeniniz için başka bir işleme döngüsü zamanlamaz. Bu, sonsuz bir işleme döngüsünden kaçınmaktır. Bu, döndürülen Task bir işlem tamamlandıktan sonra daha fazla işleme döngüsü zamanlayan diğer yaşam döngüsü yöntemlerinden farklıdır.
OnAfterRender ve OnAfterRenderAsync sunucudaki ön kayıt işlemi sırasında çağrılmaz. Bileşenler, ön kayıt sonrasında etkileşimli olarak işlendiğinde çağrılır. Uygulama yöneticileri:
- Bileşen, HTTP yanıtında bazı statik HTML işaretlemeleri oluşturmak için sunucuda yürütülür. Bu aşamada OnAfterRender OnAfterRenderAsync çağrılmaz.
- Blazor Betik (
blazor.{server|webassembly|web}.js
) tarayıcıda başlatıldığında, bileşen etkileşimli işleme modunda yeniden başlatılır. Bir bileşen yeniden başlatıldıktan OnAfterRender sonra ve OnAfterRenderAsync uygulama artık ön kayıt aşamasında olmadığından çağrılır.
Geliştirici kodunda olay işleyicileri sağlanıyorsa, bunları elden çıkarıldığında çıkarın. Daha fazla bilgi için Bileşen atma ve IDisposable
IAsyncDisposable
atma bölümüne bakın.
Temel sınıf yaşam döngüsü yöntemleri
'nin yaşam döngüsü yöntemleri geçersiz kılınırken Blazoriçin temel sınıf yaşam döngüsü yöntemlerini ComponentBaseçağırmak gerekmez. Ancak, bir bileşen aşağıdaki durumlarda geçersiz kılınmış bir temel sınıf yaşam döngüsü yöntemini çağırmalıdır:
- geçersiz kılınırken ComponentBase.SetParametersAsync
await base.SetParametersAsync(parameters);
genellikle temel sınıf yöntemi diğer yaşam döngüsü yöntemlerini çağırdığından ve karmaşık bir şekilde işlemeyi tetiklediğinden çağrılır. Daha fazla bilgi için Parametreler ayarlandığında (SetParametersAsync
) bölümüne bakın. - Temel sınıf yöntemi yürütülmesi gereken mantık içeriyorsa. Kitaplık temel sınıfları genellikle yürütülecek özel yaşam döngüsü mantığına sahip olduğundan, kitaplık tüketicileri genellikle bir temel sınıfı devralırken temel sınıf yaşam döngüsü yöntemlerini çağırır. Uygulama bir kitaplıktan temel sınıf kullanıyorsa, rehberlik için kitaplığın belgelerine bakın.
Aşağıdaki örnekte, base.OnInitialized();
temel sınıfın OnInitialized
yönteminin yürütülmesini sağlamak için çağrılır. Çağrı BlazorRocksBase2.OnInitialized
olmadan yürütülemez.
BlazorRocks2.razor
:
@page "/blazor-rocks-2"
@inherits BlazorRocksBase2
@inject ILogger<BlazorRocks2> Logger
<PageTitle>Blazor Rocks!</PageTitle>
<h1>Blazor Rocks! Example 2</h1>
<p>
@BlazorRocksText
</p>
@code {
protected override void OnInitialized()
{
Logger.LogInformation("Initialization code of BlazorRocks2 executed!");
base.OnInitialized();
}
}
@page "/blazor-rocks-2"
@inherits BlazorRocksBase2
@inject ILogger<BlazorRocks2> Logger
<PageTitle>Blazor Rocks!</PageTitle>
<h1>Blazor Rocks! Example 2</h1>
<p>
@BlazorRocksText
</p>
@code {
protected override void OnInitialized()
{
Logger.LogInformation("Initialization code of BlazorRocks2 executed!");
base.OnInitialized();
}
}
@page "/blazor-rocks-2"
@inherits BlazorRocksBase2
@inject ILogger<BlazorRocks2> Logger
<PageTitle>Blazor Rocks!</PageTitle>
<h1>Blazor Rocks! Example 2</h1>
<p>
@BlazorRocksText
</p>
@code {
protected override void OnInitialized()
{
Logger.LogInformation("Initialization code of BlazorRocks2 executed!");
base.OnInitialized();
}
}
@page "/blazor-rocks-2"
@inherits BlazorRocksBase2
@inject ILogger<BlazorRocks2> Logger
<PageTitle>Blazor Rocks!</PageTitle>
<h1>Blazor Rocks! Example 2</h1>
<p>
@BlazorRocksText
</p>
@code {
protected override void OnInitialized()
{
Logger.LogInformation("Initialization code of BlazorRocks2 executed!");
base.OnInitialized();
}
}
@page "/blazor-rocks-2"
@using Microsoft.Extensions.Logging
@inherits BlazorRocksBase2
@inject ILogger<BlazorRocks2> Logger
<h1>Blazor Rocks! Example 2</h1>
<p>
@BlazorRocksText
</p>
@code {
protected override void OnInitialized()
{
Logger.LogInformation("Initialization code of BlazorRocks2 executed!");
base.OnInitialized();
}
}
@page "/blazor-rocks-2"
@using Microsoft.Extensions.Logging
@inherits BlazorRocksBase2
@inject ILogger<BlazorRocks2> Logger
<h1>Blazor Rocks! Example 2</h1>
<p>
@BlazorRocksText
</p>
@code {
protected override void OnInitialized()
{
Logger.LogInformation("Initialization code of BlazorRocks2 executed!");
base.OnInitialized();
}
}
BlazorRocksBase2.cs
:
using Microsoft.AspNetCore.Components;
namespace BlazorSample;
public class BlazorRocksBase2 : ComponentBase
{
[Inject]
private ILogger<BlazorRocksBase2> Logger { get; set; } = default!;
public string BlazorRocksText { get; set; } = "Blazor rocks the browser!";
protected override void OnInitialized() =>
Logger.LogInformation("Initialization code of BlazorRocksBase2 executed!");
}
using Microsoft.AspNetCore.Components;
namespace BlazorSample;
public class BlazorRocksBase2 : ComponentBase
{
[Inject]
private ILogger<BlazorRocksBase2> Logger { get; set; } = default!;
public string BlazorRocksText { get; set; } = "Blazor rocks the browser!";
protected override void OnInitialized() =>
Logger.LogInformation("Initialization code of BlazorRocksBase2 executed!");
}
using Microsoft.AspNetCore.Components;
namespace BlazorSample;
public class BlazorRocksBase2 : ComponentBase
{
[Inject]
private ILogger<BlazorRocksBase2> Logger { get; set; } = default!;
public string BlazorRocksText { get; set; } =
"Blazor rocks the browser!";
protected override void OnInitialized()
{
Logger.LogInformation("Initialization code of BlazorRocksBase2 executed!");
}
}
using Microsoft.AspNetCore.Components;
namespace BlazorSample;
public class BlazorRocksBase2 : ComponentBase
{
[Inject]
private ILogger<BlazorRocksBase2> Logger { get; set; } = default!;
public string BlazorRocksText { get; set; } =
"Blazor rocks the browser!";
protected override void OnInitialized()
{
Logger.LogInformation("Initialization code of BlazorRocksBase2 executed!");
}
}
using Microsoft.AspNetCore.Components;
using Microsoft.Extensions.Logging;
namespace BlazorSample;
public class BlazorRocksBase2 : ComponentBase
{
[Inject]
private ILogger<BlazorRocksBase2> Logger { get; set; } = default!;
public string BlazorRocksText { get; set; } =
"Blazor rocks the browser!";
protected override void OnInitialized()
{
Logger.LogInformation("Initialization code of BlazorRocksBase2 executed!");
}
}
using Microsoft.AspNetCore.Components;
using Microsoft.Extensions.Logging;
namespace BlazorSample;
public class BlazorRocksBase2 : ComponentBase
{
[Inject]
private ILogger<BlazorRocksBase2> Logger { get; set; } = default!;
public string BlazorRocksText { get; set; } =
"Blazor rocks the browser!";
protected override void OnInitialized()
{
Logger.LogInformation("Initialization code of BlazorRocksBase2 executed!");
}
}
Durum değişiklikleri (StateHasChanged
)
StateHasChanged bileşene durumunun değiştiğini bildirir. Uygun olduğunda, çağrı, StateHasChanged uygulamanın ana iş parçacığı boş olduğunda oluşan bir rerender'ı sıralar.
StateHasChanged , yöntemler için EventCallback otomatik olarak çağrılır. Olay geri çağırmaları hakkında daha fazla bilgi için bkz . ASP.NET Core Blazor olay işleme.
Bileşen işleme ve ile ne zaman çağrılacakları StateHasChangedhakkında daha fazla bilgi için bkz. ASP.NET Temel Razor bileşen işleme.ComponentBase.InvokeAsync
İşleme sırasında tamamlanmamış zaman uyumsuz eylemleri işleme
Bileşen işlenmeden önce yaşam döngüsü olaylarında gerçekleştirilen zaman uyumsuz eylemler tamamlanmamış olabilir. Yaşam döngüsü yöntemi yürütülürken nesneler verilerle doldurulabilir veya tamamlanmamış olabilir null
. Nesnelerin başlatıldığını onaylamak için işleme mantığı sağlayın. Yer tutucu kullanıcı arabirimi öğelerini (örneğin, bir yükleme iletisi) işlerken nesneler olur null
.
Aşağıdaki bileşende, OnInitializedAsync film derecelendirme verilerinimovies
() zaman uyumsuz olarak sağlamak için geçersiz kılınmış. olduğunda movies
null
, kullanıcıya bir yükleme iletisi görüntülenir. Task
tarafından döndürülen OnInitializedAsync tamamlandıktan sonra bileşen güncelleştirilmiş durumla yeniden oluşturulur.
<h1>Sci-Fi Movie Ratings</h1>
@if (movies == null)
{
<p><em>Loading...</em></p>
}
else
{
<ul>
@foreach (var movie in movies)
{
<li>@movie.Title — @movie.Rating</li>
}
</ul>
}
@code {
private Movies[]? movies;
protected override async Task OnInitializedAsync()
{
movies = await GetMovieRatings(DateTime.Now);
}
}
Hataları işleme
Yaşam döngüsü yöntemi yürütme sırasındaki hataları işleme hakkında bilgi için bkz . ASP.NET Core Blazor uygulamalarında hataları işleme.
Prerendering sonrasında durum bilgisi olan yeniden bağlantı
Sunucuda önceden oturum açılırken, başlangıçta bir bileşen sayfanın bir parçası olarak statik olarak işlenir. Tarayıcı sunucuyla yeniden bağlantı SignalR kurduktan sonra bileşen yeniden işlenir ve etkileşimli olur. OnInitialized{Async}
Bileşeni başlatmak için yaşam döngüsü yöntemi varsa, yöntem iki kez yürütülür:
- Bileşen statik olarak önceden girildiğinde.
- Sunucu bağlantısı kurulduktan sonra.
Bu, bileşen sonunda işlendiğinde kullanıcı arabiriminde görüntülenen verilerde belirgin bir değişikliğe neden olabilir. Bu davranışı önlemek için, ön kayıt sırasında durumu önbelleğe almak ve ön kayıttan sonra durumu almak için bir tanımlayıcı geçirin.
Aşağıdaki kod, ön kayıt nedeniyle veri görüntüsündeki değişikliği önleyen bir WeatherForecastService
gösterir. Beklenen Delay (await Task.Delay(...)
) yönteminden veri döndürmeden önce kısa bir gecikmenin benzetimini gerçekleştirmektedir GetForecastAsync
.
Uygulamasının Program
dosyasındaki hizmet koleksiyonunda ile hizmetlerini AddMemoryCache ekleyinIMemoryCache:
builder.Services.AddMemoryCache();
WeatherForecastService.cs
:
using Microsoft.Extensions.Caching.Memory;
namespace BlazorSample;
public class WeatherForecastService(IMemoryCache memoryCache)
{
private static readonly string[] summaries =
[
"Freezing", "Bracing", "Chilly", "Cool", "Mild",
"Warm", "Balmy", "Hot", "Sweltering", "Scorching"
];
public IMemoryCache MemoryCache { get; } = memoryCache;
public Task<WeatherForecast[]?> GetForecastAsync(DateOnly startDate)
{
return MemoryCache.GetOrCreateAsync(startDate, async e =>
{
e.SetOptions(new MemoryCacheEntryOptions
{
AbsoluteExpirationRelativeToNow =
TimeSpan.FromSeconds(30)
});
await Task.Delay(TimeSpan.FromSeconds(10));
return Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
Date = startDate.AddDays(index),
TemperatureC = Random.Shared.Next(-20, 55),
Summary = summaries[Random.Shared.Next(summaries.Length)]
}).ToArray();
});
}
}
using Microsoft.Extensions.Caching.Memory;
namespace BlazorSample;
public class WeatherForecastService(IMemoryCache memoryCache)
{
private static readonly string[] summaries =
[
"Freezing", "Bracing", "Chilly", "Cool", "Mild",
"Warm", "Balmy", "Hot", "Sweltering", "Scorching"
];
public IMemoryCache MemoryCache { get; } = memoryCache;
public Task<WeatherForecast[]?> GetForecastAsync(DateOnly startDate)
{
return MemoryCache.GetOrCreateAsync(startDate, async e =>
{
e.SetOptions(new MemoryCacheEntryOptions
{
AbsoluteExpirationRelativeToNow =
TimeSpan.FromSeconds(30)
});
await Task.Delay(TimeSpan.FromSeconds(10));
return Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
Date = startDate.AddDays(index),
TemperatureC = Random.Shared.Next(-20, 55),
Summary = summaries[Random.Shared.Next(summaries.Length)]
}).ToArray();
});
}
}
using Microsoft.Extensions.Caching.Memory;
public class WeatherForecastService
{
private static readonly string[] summaries = new[]
{
"Freezing", "Bracing", "Chilly", "Cool", "Mild",
"Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};
public WeatherForecastService(IMemoryCache memoryCache)
{
MemoryCache = memoryCache;
}
public IMemoryCache MemoryCache { get; }
public Task<WeatherForecast[]?> GetForecastAsync(DateTime startDate)
{
return MemoryCache.GetOrCreateAsync(startDate, async e =>
{
e.SetOptions(new MemoryCacheEntryOptions
{
AbsoluteExpirationRelativeToNow =
TimeSpan.FromSeconds(30)
});
await Task.Delay(TimeSpan.FromSeconds(10));
return Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
Date = startDate.AddDays(index),
TemperatureC = Random.Shared.Next(-20, 55),
Summary = summaries[Random.Shared.Next(summaries.Length)]
}).ToArray();
});
}
}
using Microsoft.Extensions.Caching.Memory;
public class WeatherForecastService
{
private static readonly string[] summaries = new[]
{
"Freezing", "Bracing", "Chilly", "Cool", "Mild",
"Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};
public WeatherForecastService(IMemoryCache memoryCache)
{
MemoryCache = memoryCache;
}
public IMemoryCache MemoryCache { get; }
public Task<WeatherForecast[]> GetForecastAsync(DateTime startDate)
{
return MemoryCache.GetOrCreateAsync(startDate, async e =>
{
e.SetOptions(new MemoryCacheEntryOptions
{
AbsoluteExpirationRelativeToNow =
TimeSpan.FromSeconds(30)
});
await Task.Delay(TimeSpan.FromSeconds(10));
return Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
Date = startDate.AddDays(index),
TemperatureC = Random.Shared.Next(-20, 55),
Summary = summaries[Random.Shared.Next(summaries.Length)]
}).ToArray();
});
}
}
using System;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.Caching.Memory;
using BlazorSample.Shared;
public class WeatherForecastService
{
private static readonly string[] summaries = new[]
{
"Freezing", "Bracing", "Chilly", "Cool", "Mild",
"Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};
public WeatherForecastService(IMemoryCache memoryCache)
{
MemoryCache = memoryCache;
}
public IMemoryCache MemoryCache { get; }
public Task<WeatherForecast[]> GetForecastAsync(DateTime startDate)
{
return MemoryCache.GetOrCreateAsync(startDate, async e =>
{
e.SetOptions(new MemoryCacheEntryOptions
{
AbsoluteExpirationRelativeToNow =
TimeSpan.FromSeconds(30)
});
var rng = new Random();
await Task.Delay(TimeSpan.FromSeconds(10));
return Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
Date = startDate.AddDays(index),
TemperatureC = rng.Next(-20, 55),
Summary = summaries[rng.Next(summaries.Length)]
}).ToArray();
});
}
}
using System;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.Caching.Memory;
using BlazorSample.Shared;
public class WeatherForecastService
{
private static readonly string[] summaries = new[]
{
"Freezing", "Bracing", "Chilly", "Cool", "Mild",
"Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};
public WeatherForecastService(IMemoryCache memoryCache)
{
MemoryCache = memoryCache;
}
public IMemoryCache MemoryCache { get; }
public Task<WeatherForecast[]> GetForecastAsync(DateTime startDate)
{
return MemoryCache.GetOrCreateAsync(startDate, async e =>
{
e.SetOptions(new MemoryCacheEntryOptions
{
AbsoluteExpirationRelativeToNow =
TimeSpan.FromSeconds(30)
});
var rng = new Random();
await Task.Delay(TimeSpan.FromSeconds(10));
return Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
Date = startDate.AddDays(index),
TemperatureC = rng.Next(-20, 55),
Summary = summaries[rng.Next(summaries.Length)]
}).ToArray();
});
}
}
hakkında RenderModedaha fazla bilgi için bkz . ASP.NET Temel BlazorSignalR kılavuzu.
Bu bölümdeki içerik, s ve durum bilgisi olan SignalRyeniden bağlanmaya odaklanırBlazor Web App. Ön kayıt sırasında başlatma kodunun yürütülmesi sırasında durumu korumak için bkz . Prerender ASP.NET Core Razor bileşenleri.
Bu bölümdeki içerik, durum bilgisi olanSignalR yeniden bağlanmaya odaklansa Blazor Server da, barındırılan Blazor WebAssembly çözümlerde (WebAssemblyPrerendered) önceden giriş senaryosu, geliştirici kodunun iki kez yürütülmesini önlemek için benzer koşullar ve yaklaşımlar içerir. Hazırlama sırasında başlatma kodunun yürütülmesi sırasında durumu korumak için bkz . Prerender ve ASP.NET Core Razor bileşenlerini tümleştirme.
JavaScript birlikte çalışma ile ön kayıt
Bu bölüm, bileşenleri önceden Razor oluşturan sunucu tarafı uygulamalar için geçerlidir. Prerendering, Prerender ASP.NET Core bileşenlerinde ele alınmıştır.Razor
Not
'de Blazor Web Appetkileşimli yönlendirme için iç gezinti, sunucudan yeni sayfa içeriği istemeyi içermez. Bu nedenle, iç sayfa istekleri için ön kayıt gerçekleşmez. Uygulama etkileşimli yönlendirmeyi benimsediyse, önyükleme davranışını gösteren bileşen örnekleri için tam sayfa yeniden yükleme gerçekleştirin. Daha fazla bilgi için bkz . Prerender ASP.NET Core Razor bileşenleri.
Bu bölüm, sunucu tarafı uygulamalar ve bileşenleri önceden Razor oluşturan barındırılan Blazor WebAssembly uygulamalar için geçerlidir. Prerendering, Prerender kapsamındadır ve ASP.NET Core Razor bileşenlerini tümleştirir.
Ön kayıt sırasında JavaScript'e (JS) çağrı yapılamaz. Aşağıdaki örnekte, bir bileşenin başlatma mantığının bir parçası olarak birlikte çalışma özelliğinin, ön kayıtla uyumlu bir şekilde nasıl kullanılacağı JS gösterilmektedir.
Aşağıdaki scrollElementIntoView
işlev:
- ile geçirilen öğesine kayar
scrollIntoView
. - yönteminden
getBoundingClientRect
öğenintop
özellik değerini döndürür.
window.scrollElementIntoView = (element) => {
element.scrollIntoView();
return element.getBoundingClientRect().top;
}
İşlevi JS bileşen kodunda çağırdığı durumlardaIJSRuntime.InvokeAsync, bileşen işleninceye ElementReference kadar HTML DOM öğesi olmadığından yalnızca içinde kullanılır OnAfterRenderAsync ve önceki yaşam döngüsü yöntemlerinde kullanılmaz.
StateHasChanged
(başvuru kaynağı) birlikte çalışma çağrısından JS alınan yeni durumla bileşeni yeniden sıralamak için çağrılır (daha fazla bilgi için bkz . ASP.NET Core Razor bileşeni işleme). Sonsuz döngü oluşturulmaz çünkü StateHasChanged yalnızca olduğunda scrollPosition
çağrılır null
.
PrerenderedInterop.razor
:
@page "/prerendered-interop"
@using Microsoft.AspNetCore.Components
@using Microsoft.JSInterop
@inject IJSRuntime JS
<PageTitle>Prerendered Interop</PageTitle>
<h1>Prerendered Interop Example</h1>
<div @ref="divElement" style="margin-top:2000px">
Set value via JS interop call: <strong>@scrollPosition</strong>
</div>
@code {
private ElementReference divElement;
private double? scrollPosition;
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender && scrollPosition is null)
{
scrollPosition = await JS.InvokeAsync<double>(
"scrollElementIntoView", divElement);
StateHasChanged();
}
}
}
@page "/prerendered-interop"
@using Microsoft.AspNetCore.Components
@using Microsoft.JSInterop
@inject IJSRuntime JS
<h1>Prerendered Interop Example</h1>
<div @ref="divElement" style="margin-top:2000px">
Set value via JS interop call: <strong>@scrollPosition</strong>
</div>
@code {
private ElementReference divElement;
private double? scrollPosition;
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender && scrollPosition is null)
{
scrollPosition = await JS.InvokeAsync<double>(
"scrollElementIntoView", divElement);
StateHasChanged();
}
}
}
@page "/prerendered-interop"
@using Microsoft.AspNetCore.Components
@using Microsoft.JSInterop
@inject IJSRuntime JS
<h1>Prerendered Interop Example</h1>
<div @ref="divElement" style="margin-top:2000px">
Set value via JS interop call: <strong>@scrollPosition</strong>
</div>
@code {
private ElementReference divElement;
private double? scrollPosition;
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender && scrollPosition is null)
{
scrollPosition = await JS.InvokeAsync<double>(
"scrollElementIntoView", divElement);
StateHasChanged();
}
}
}
@page "/prerendered-interop"
@using Microsoft.AspNetCore.Components
@using Microsoft.JSInterop
@inject IJSRuntime JS
<h1>Prerendered Interop Example</h1>
<div @ref="divElement" style="margin-top:2000px">
Set value via JS interop call: <strong>@scrollPosition</strong>
</div>
@code {
private ElementReference divElement;
private double? scrollPosition;
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender && scrollPosition is null)
{
scrollPosition = await JS.InvokeAsync<double>(
"scrollElementIntoView", divElement);
StateHasChanged();
}
}
}
@page "/prerendered-interop"
@using Microsoft.AspNetCore.Components
@using Microsoft.JSInterop
@inject IJSRuntime JS
<h1>Prerendered Interop Example</h1>
<div @ref="divElement" style="margin-top:2000px">
Set value via JS interop call: <strong>@scrollPosition</strong>
</div>
@code {
private ElementReference divElement;
private double? scrollPosition;
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender && scrollPosition is null)
{
scrollPosition = await JS.InvokeAsync<double>(
"scrollElementIntoView", divElement);
StateHasChanged();
}
}
}
Yukarıdaki örnek, istemciyi genel bir işlevle kirletir. Üretim uygulamalarında daha iyi bir yaklaşım için bkz . JavaScript modüllerinde JavaScript yalıtımı.
ve ile IDisposable
bileşen bertarafı IAsyncDisposable
Bir bileşen veya IAsyncDisposableuygularsaIDisposable, bileşen kullanıcı arabiriminden kaldırıldığında çerçeve kaynak atılması için çağrıda bulunur. Bu yöntemlerin yürütülürken tam zamanlamasına güvenmeyin. Örneğin, IAsyncDisposable içinde beklenen OnInitalizedAsync
bir zaman uyumsuz Task çağrılmadan veya tamamlandıktan önce veya sonra tetiklenebilir. Ayrıca, nesne atma kodu başlatma sırasında oluşturulan nesnelerin veya diğer yaşam döngüsü yöntemlerinin mevcut olduğunu varsaymamalıdır.
Bileşenlerin aynı anda ve IAsyncDisposable uygulaması IDisposable gerekmez. Her ikisi de uygulanırsa, çerçeve yalnızca zaman uyumsuz aşırı yüklemeyi yürütür.
Geliştirici kodu, uygulamaların tamamlanmasının IAsyncDisposable uzun sürmediğinden emin olmalıdır.
JavaScript birlikte çalışma nesnesi başvurularının elden çıkarılması
JavaScript (JS) birlikte çalışma makalelerinin tüm örnekleri tipik nesne atma desenlerini gösterir:
.NET'ten çağırırkenJS, ASP.NET Core'daki Blazor.NET yöntemlerinden JavaScript işlevlerini çağırma bölümünde açıklandığı gibi, bellek sızıntısını JS önlemek için .NET'ten veya kaynağından JS oluşturulanlarıJSObjectReference IJSObjectReference/IJSInProcessObjectReference/atın.
.NET JSçağrısı yaparken, ASP.NET Core'daki BlazorJavaScript işlevlerinden .NET yöntemlerini çağırma bölümünde açıklandığı gibi , .NET belleğinin sızmasını önlemek için .NET'ten veya kaynağından JS oluşturulan DotNetObjectReference bir öğesini atın.
JS birlikte çalışma nesne başvuruları, birlikte çalışma çağrısının JS yanında başvuruyu oluşturan bir tanımlayıcı tarafından anahtarlanan bir eşleme olarak uygulanır. Nesne atma işlemi .NET'ten veya JS taraftan başlatıldığında, Blazor girdiyi eşlemeden kaldırır ve nesneye başka güçlü bir başvuru olmadığı sürece nesne çöp olarak toplanabilir.
.NET yönetilen belleğinin sızmasını önlemek için en azından .NET tarafında oluşturulan nesneleri her zaman atın.
Bileşen atma sırasında DOM temizleme görevleri
Daha fazla bilgi için bkz. ASP.NET Core Blazor JavaScript birlikte çalışabilirliği (JSbirlikte çalışma).
Bağlantı hattının JSDisconnectedException bağlantısının kesildiğinde yönergeler için bkz . ASP.NET Core Blazor JavaScript birlikte çalışabilirliği (JS birlikte çalışma). Genel JavaScript birlikte çalışma hatası işleme yönergeleri için ASP.NET Core uygulamalarında hataları işleme bölümündeki JavaScript birlikte çalışma bölümüne bakın.Blazor
Eşzamanlı IDisposable
Zaman uyumlu atma görevleri için kullanın IDisposable.Dispose.
Aşağıdaki bileşen:
- IDisposable yönergesi
@implements
Razor ile uygular. obj
uygulayan bir tür olan öğesini atılırIDisposable.- Bir yaşam döngüsü yönteminde oluşturulduğundan
obj
(gösterilmediğinden) null denetim gerçekleştirilir.
@implements IDisposable
...
@code {
...
public void Dispose()
{
obj?.Dispose();
}
}
Tek bir nesnenin atılması gerekiyorsa, çağrıldığında Dispose nesnenin atılması için bir lambda kullanılabilir. Aşağıdaki örnek, ASP.NET Core Razor bileşeni işleme makalesinde gösterilir ve bir öğesinin atılması için lambda ifadesinin Timerkullanımını gösterir.
TimerDisposal1.razor
:
@page "/timer-disposal-1"
@using System.Timers
@implements IDisposable
<PageTitle>Timer Disposal 1</PageTitle>
<h1>Timer Disposal Example 1</h1>
<p>Current count: @currentCount</p>
@code {
private int currentCount = 0;
private Timer timer = new(1000);
protected override void OnInitialized()
{
timer.Elapsed += (sender, eventArgs) => OnTimerCallback();
timer.Start();
}
private void OnTimerCallback()
{
_ = InvokeAsync(() =>
{
currentCount++;
StateHasChanged();
});
}
public void Dispose() => timer.Dispose();
}
TimerDisposal1.razor
:
@page "/timer-disposal-1"
@using System.Timers
@implements IDisposable
<PageTitle>Timer Disposal 1</PageTitle>
<h1>Timer Disposal Example 1</h1>
<p>Current count: @currentCount</p>
@code {
private int currentCount = 0;
private Timer timer = new(1000);
protected override void OnInitialized()
{
timer.Elapsed += (sender, eventArgs) => OnTimerCallback();
timer.Start();
}
private void OnTimerCallback()
{
_ = InvokeAsync(() =>
{
currentCount++;
StateHasChanged();
});
}
public void Dispose() => timer.Dispose();
}
CounterWithTimerDisposal1.razor
:
@page "/counter-with-timer-disposal-1"
@using System.Timers
@implements IDisposable
<h1>Counter with <code>Timer</code> disposal</h1>
<p>Current count: @currentCount</p>
@code {
private int currentCount = 0;
private Timer timer = new(1000);
protected override void OnInitialized()
{
timer.Elapsed += (sender, eventArgs) => OnTimerCallback();
timer.Start();
}
private void OnTimerCallback()
{
_ = InvokeAsync(() =>
{
currentCount++;
StateHasChanged();
});
}
public void Dispose() => timer.Dispose();
}
CounterWithTimerDisposal1.razor
:
@page "/counter-with-timer-disposal-1"
@using System.Timers
@implements IDisposable
<h1>Counter with <code>Timer</code> disposal</h1>
<p>Current count: @currentCount</p>
@code {
private int currentCount = 0;
private Timer timer = new(1000);
protected override void OnInitialized()
{
timer.Elapsed += (sender, eventArgs) => OnTimerCallback();
timer.Start();
}
private void OnTimerCallback()
{
_ = InvokeAsync(() =>
{
currentCount++;
StateHasChanged();
});
}
public void Dispose() => timer.Dispose();
}
CounterWithTimerDisposal1.razor
:
@page "/counter-with-timer-disposal-1"
@using System.Timers
@implements IDisposable
<h1>Counter with <code>Timer</code> disposal</h1>
<p>Current count: @currentCount</p>
@code {
private int currentCount = 0;
private Timer timer = new(1000);
protected override void OnInitialized()
{
timer.Elapsed += (sender, eventArgs) => OnTimerCallback();
timer.Start();
}
private void OnTimerCallback()
{
_ = InvokeAsync(() =>
{
currentCount++;
StateHasChanged();
});
}
public void Dispose() => timer.Dispose();
}
CounterWithTimerDisposal1.razor
:
@page "/counter-with-timer-disposal-1"
@using System.Timers
@implements IDisposable
<h1>Counter with <code>Timer</code> disposal</h1>
<p>Current count: @currentCount</p>
@code {
private int currentCount = 0;
private Timer timer = new Timer(1000);
protected override void OnInitialized()
{
timer.Elapsed += (sender, eventArgs) => OnTimerCallback();
timer.Start();
}
private void OnTimerCallback()
{
_ = InvokeAsync(() =>
{
currentCount++;
StateHasChanged();
});
}
public void Dispose() => timer.Dispose();
}
Not
Yukarıdaki örnekte, geri çağırma'nın StateHasChanged ComponentBase.InvokeAsync eşitleme bağlamının Blazordışında çağrıldığından çağrısı çağrısı ile sarmalanır. Daha fazla bilgi için bkz. ASP.NET Core Razor bileşenini işleme.
Nesnesi gibi OnInitialized{Async}
bir yaşam döngüsü yönteminde oluşturulduysa çağrısından Dispose
önce öğesini null
denetleyin.
TimerDisposal2.razor
:
@page "/timer-disposal-2"
@using System.Timers
@implements IDisposable
<PageTitle>Timer Disposal 2</PageTitle>
<h1>Timer Disposal Example 2</h1>
<p>Current count: @currentCount</p>
@code {
private int currentCount = 0;
private Timer? timer;
protected override void OnInitialized()
{
timer = new Timer(1000);
timer.Elapsed += (sender, eventArgs) => OnTimerCallback();
timer.Start();
}
private void OnTimerCallback()
{
_ = InvokeAsync(() =>
{
currentCount++;
StateHasChanged();
});
}
public void Dispose() => timer?.Dispose();
}
TimerDisposal2.razor
:
@page "/timer-disposal-2"
@using System.Timers
@implements IDisposable
<PageTitle>Timer Disposal 2</PageTitle>
<h1>Timer Disposal Example 2</h1>
<p>Current count: @currentCount</p>
@code {
private int currentCount = 0;
private Timer? timer;
protected override void OnInitialized()
{
timer = new Timer(1000);
timer.Elapsed += (sender, eventArgs) => OnTimerCallback();
timer.Start();
}
private void OnTimerCallback()
{
_ = InvokeAsync(() =>
{
currentCount++;
StateHasChanged();
});
}
public void Dispose() => timer?.Dispose();
}
CounterWithTimerDisposal2.razor
:
@page "/counter-with-timer-disposal-2"
@using System.Timers
@implements IDisposable
<h1>Counter with <code>Timer</code> disposal</h1>
<p>Current count: @currentCount</p>
@code {
private int currentCount = 0;
private Timer? timer;
protected override void OnInitialized()
{
timer = new Timer(1000);
timer.Elapsed += (sender, eventArgs) => OnTimerCallback();
timer.Start();
}
private void OnTimerCallback()
{
_ = InvokeAsync(() =>
{
currentCount++;
StateHasChanged();
});
}
public void Dispose() => timer?.Dispose();
}
CounterWithTimerDisposal2.razor
:
@page "/counter-with-timer-disposal-2"
@using System.Timers
@implements IDisposable
<h1>Counter with <code>Timer</code> disposal</h1>
<p>Current count: @currentCount</p>
@code {
private int currentCount = 0;
private Timer? timer;
protected override void OnInitialized()
{
timer = new Timer(1000);
timer.Elapsed += (sender, eventArgs) => OnTimerCallback();
timer.Start();
}
private void OnTimerCallback()
{
_ = InvokeAsync(() =>
{
currentCount++;
StateHasChanged();
});
}
public void Dispose() => timer?.Dispose();
}
CounterWithTimerDisposal2.razor
:
@page "/counter-with-timer-disposal-2"
@using System.Timers
@implements IDisposable
<h1>Counter with <code>Timer</code> disposal</h1>
<p>Current count: @currentCount</p>
@code {
private int currentCount = 0;
private Timer timer;
protected override void OnInitialized()
{
timer = new Timer(1000);
timer.Elapsed += (sender, eventArgs) => OnTimerCallback();
timer.Start();
}
private void OnTimerCallback()
{
_ = InvokeAsync(() =>
{
currentCount++;
StateHasChanged();
});
}
public void Dispose() => timer?.Dispose();
}
CounterWithTimerDisposal2.razor
:
@page "/counter-with-timer-disposal-2"
@using System.Timers
@implements IDisposable
<h1>Counter with <code>Timer</code> disposal</h1>
<p>Current count: @currentCount</p>
@code {
private int currentCount = 0;
private Timer timer;
protected override void OnInitialized()
{
timer = new Timer(1000);
timer.Elapsed += (sender, eventArgs) => OnTimerCallback();
timer.Start();
}
private void OnTimerCallback()
{
_ = InvokeAsync(() =>
{
currentCount++;
StateHasChanged();
});
}
public void Dispose() => timer?.Dispose();
}
Daha fazla bilgi için bkz.
Eşzamansız IAsyncDisposable
Zaman uyumsuz elden çıkarma görevleri için kullanın IAsyncDisposable.DisposeAsync.
Aşağıdaki bileşen:
- IAsyncDisposable yönergesi
@implements
Razor ile uygular. obj
uygulayan yönetilmeyen bir tür olan öğesini atılırIAsyncDisposable.- Bir yaşam döngüsü yönteminde oluşturulduğundan
obj
(gösterilmediğinden) null denetim gerçekleştirilir.
@implements IAsyncDisposable
...
@code {
...
public async ValueTask DisposeAsync()
{
if (obj is not null)
{
await obj.DisposeAsync();
}
}
}
Daha fazla bilgi için bkz.
null
Atılan nesnelere atama
Genellikle, çağrısı Dispose/DisposeAsyncyaptıktan sonra atılan nesnelere atamanız null
gerekmez. Nadir atama null
örnekleri şunlardır:
- Nesnenin türü kötü uygulandıysa ve öğesine yapılan yineleme çağrılarını DisposeDisposeAsync/tolere etmiyorsa, öğesine yapılan diğer çağrıları/DisposeAsyncDispose düzgün bir şekilde atlamak için elden çıkarmadan sonra atlayın.
null
- Uzun süreli bir işlem, atılan bir nesneye başvuruyu tutmaya devam ederse, atama
null
işlemi, atık toplayıcının uzun ömürlü bir işlem başvuruyu tutmasına rağmen nesneyi serbest bırakmasını sağlar.
Bunlar olağan dışı senaryolardır. Doğru uygulanan ve normal davranan nesneler için, atılan nesnelere atamanın null
bir anlamı yoktur. Bir nesnenin atanması null
gereken nadir durumlarda nedenini belgelemenizi ve atama null
gereksinimini önleyen bir çözüm aramanızı öneririz.
StateHasChanged
Not
ve StateHasChanged DisposeAsync
çağrısı Dispose
desteklenmez. StateHasChanged işleyiciyi yok etme işleminin bir parçası olarak çağrılabilir, bu nedenle bu noktada kullanıcı arabirimi güncelleştirmeleri istenmesi desteklenmez.
Olay işleyicileri
.NET olaylarından olay işleyicilerinin aboneliğini her zaman kaldırın. Aşağıdaki Blazor form örneklerinde yöntemindeki bir olay işleyicisinin aboneliğinin nasıl kaldırılacağı gösterilmektedir Dispose
:
Özel alan ve lambda yaklaşımı
@implements IDisposable <EditForm ... EditContext="editContext" ...> ... <button type="submit" disabled="@formInvalid">Submit</button> </EditForm> @code { ... private EventHandler<FieldChangedEventArgs>? fieldChanged; protected override void OnInitialized() { editContext = new(model); fieldChanged = (_, __) => { ... }; editContext.OnFieldChanged += fieldChanged; } public void Dispose() { editContext.OnFieldChanged -= fieldChanged; } }
Özel yöntem yaklaşımı
@implements IDisposable <EditForm ... EditContext="editContext" ...> ... <button type="submit" disabled="@formInvalid">Submit</button> </EditForm> @code { ... protected override void OnInitialized() { editContext = new(model); editContext.OnFieldChanged += HandleFieldChanged; } private void HandleFieldChanged(object sender, FieldChangedEventArgs e) { ... } public void Dispose() { editContext.OnFieldChanged -= HandleFieldChanged; } }
Daha fazla bilgi için ve IAsyncDisposable
ile IDisposable
bileşen elden çıkarma bölümüne bakın.
Bileşen ve formlar hakkında EditForm daha fazla bilgi için bkz. ASP.NET Çekirdek Blazor formlarına genel bakış ve Formlar düğümündeki diğer form makaleleri.
Anonim işlevler, yöntemler ve ifadeler
Anonim işlevler, yöntemler veya ifadeler kullanıldığında, temsilcilerin uygulanması IDisposable ve aboneliğinin iptal edilmesi gerekmez. Ancak, bir temsilcinin aboneliğinin kaldırılamaması, olayı ortaya çıkartan nesnenin temsilciyi kaydeden bileşenin ömründen uzun süre geçtiği bir sorundur. Bu durum oluştuğunda, kayıtlı temsilci özgün nesneyi canlı tuttuğundan bellek sızıntısı oluşur. Bu nedenle, yalnızca olay temsilcisinin hızlı bir şekilde attığını bildiğinizde aşağıdaki yaklaşımları kullanın. Elden çıkarma gerektiren nesnelerin kullanım ömrü hakkında şüpheler olduğunda, bir temsilci yöntemine abone olun ve önceki örneklerde gösterildiği gibi temsilciyi düzgün bir şekilde atın.
Anonim lambda yöntemi yaklaşımı (açık elden çıkarma gerekli değildir):
private void HandleFieldChanged(object sender, FieldChangedEventArgs e) { formInvalid = !editContext.Validate(); StateHasChanged(); } protected override void OnInitialized() { editContext = new(starship); editContext.OnFieldChanged += (s, e) => HandleFieldChanged((editContext)s, e); }
Anonim lambda ifade yaklaşımı (açık elden çıkarma gerekli değildir):
private ValidationMessageStore? messageStore; [CascadingParameter] private EditContext? CurrentEditContext { get; set; } protected override void OnInitialized() { ... messageStore = new(CurrentEditContext); CurrentEditContext.OnValidationRequested += (s, e) => messageStore.Clear(); CurrentEditContext.OnFieldChanged += (s, e) => messageStore.Clear(e.FieldIdentifier); }
Anonim lambda ifadeleri içeren önceki kodun tam örneği ASP.NET Core Blazor formları doğrulama makalesinde görünür.
Daha fazla bilgi için bkz. Yönetilmeyen kaynakları temizleme ve ve DisposeAsync
yöntemlerini uygulama Dispose
konusunda bunu izleyen konular.
İptal edilebilir arka plan çalışması
Bileşenler genellikle ağ çağrıları (HttpClient) yapma ve veritabanlarıyla etkileşim kurma gibi uzun süre çalışan arka plan işleri gerçekleştirir. Sistem kaynaklarını çeşitli durumlarda korumak için arka plan çalışmasını durdurmak tercih edilir. Örneğin, kullanıcı bir bileşenden uzaklaştığında arka plan zaman uyumsuz işlemleri otomatik olarak durmaz.
Arka plan iş öğelerinin iptal gerektirmesi için diğer nedenler şunlardır:
- Hatalı giriş verileri veya işleme parametreleriyle bir yürütme arka plan görevi başlatıldı.
- Geçerli yürütme arka plan iş öğeleri kümesi yeni bir iş öğeleri kümesiyle değiştirilmelidir.
- Şu anda yürütülmekte olan görevlerin önceliği değiştirilmelidir.
- Sunucu yeniden dağıtımı için uygulamanın kapatılması gerekir.
- Sunucu kaynakları sınırlı hale gelir ve arka plan iş öğelerinin yeniden zamanlanması gerekir.
Bir bileşende iptal edilebilir bir arka plan çalışma deseni uygulamak için:
- CancellationTokenSource ve CancellationTokenkullanın.
- Bileşenin elden çıkarılması ve herhangi bir noktada iptal edilmesi isteniyorsa belirteci el ile iptal ederek arka plan çalışmasının iptal edilmesi gerektiğini belirten bir çağrı
CancellationTokenSource.Cancel
yapın. - Zaman uyumsuz çağrı döndürdüğünde belirteçte çağrısında ThrowIfCancellationRequested bulunur.
Aşağıdaki örnekte:
await Task.Delay(5000, cts.Token);
uzun süre çalışan zaman uyumsuz arka plan çalışmasını temsil eder.BackgroundResourceMethod
, yöntemi çağrılmadan önce atılırsaResource
başlatılmaması gereken uzun süre çalışan bir arka plan yöntemini temsil eder.
BackgroundWork.razor
:
@page "/background-work"
@implements IDisposable
@inject ILogger<BackgroundWork> Logger
<PageTitle>Background Work</PageTitle>
<h1>Background Work Example</h1>
<p>
<button @onclick="LongRunningWork">Trigger long running work</button>
<button @onclick="Dispose">Trigger Disposal</button>
</p>
<p>Study logged messages in the console.</p>
<p>
If you trigger disposal within 10 seconds of page load, the
<code>BackgroundResourceMethod</code> isn't executed.
</p>
<p>
If disposal occurs after <code>BackgroundResourceMethod</code> is called but
before action is taken on the resource, an <code>ObjectDisposedException</code>
is thrown by <code>BackgroundResourceMethod</code>, and the resource isn't
processed.
</p>
@code {
private Resource resource = new();
private CancellationTokenSource cts = new();
private IList<string> messages = [];
protected async Task LongRunningWork()
{
Logger.LogInformation("Long running work started");
await Task.Delay(10000, cts.Token);
cts.Token.ThrowIfCancellationRequested();
resource.BackgroundResourceMethod(Logger);
}
public void Dispose()
{
Logger.LogInformation("Executing Dispose");
if (!cts.IsCancellationRequested)
{
cts.Cancel();
}
cts?.Dispose();
resource?.Dispose();
}
private class Resource : IDisposable
{
private bool disposed;
public void BackgroundResourceMethod(ILogger<BackgroundWork> logger)
{
logger.LogInformation("BackgroundResourceMethod: Start method");
if (disposed)
{
logger.LogInformation("BackgroundResourceMethod: Disposed");
throw new ObjectDisposedException(nameof(Resource));
}
// Take action on the Resource
logger.LogInformation("BackgroundResourceMethod: Action on Resource");
}
public void Dispose() => disposed = true;
}
}
@page "/background-work"
@implements IDisposable
@inject ILogger<BackgroundWork> Logger
<PageTitle>Background Work</PageTitle>
<h1>Background Work Example</h1>
<p>
<button @onclick="LongRunningWork">Trigger long running work</button>
<button @onclick="Dispose">Trigger Disposal</button>
</p>
<p>Study logged messages in the console.</p>
<p>
If you trigger disposal within 10 seconds of page load, the
<code>BackgroundResourceMethod</code> isn't executed.
</p>
<p>
If disposal occurs after <code>BackgroundResourceMethod</code> is called but
before action is taken on the resource, an <code>ObjectDisposedException</code>
is thrown by <code>BackgroundResourceMethod</code>, and the resource isn't
processed.
</p>
@code {
private Resource resource = new();
private CancellationTokenSource cts = new();
private IList<string> messages = [];
protected async Task LongRunningWork()
{
Logger.LogInformation("Long running work started");
await Task.Delay(10000, cts.Token);
cts.Token.ThrowIfCancellationRequested();
resource.BackgroundResourceMethod(Logger);
}
public void Dispose()
{
Logger.LogInformation("Executing Dispose");
if (!cts.IsCancellationRequested)
{
cts.Cancel();
}
cts?.Dispose();
resource?.Dispose();
}
private class Resource : IDisposable
{
private bool disposed;
public void BackgroundResourceMethod(ILogger<BackgroundWork> logger)
{
logger.LogInformation("BackgroundResourceMethod: Start method");
if (disposed)
{
logger.LogInformation("BackgroundResourceMethod: Disposed");
throw new ObjectDisposedException(nameof(Resource));
}
// Take action on the Resource
logger.LogInformation("BackgroundResourceMethod: Action on Resource");
}
public void Dispose() => disposed = true;
}
}
@page "/background-work"
@using System.Threading
@using Microsoft.Extensions.Logging
@implements IDisposable
@inject ILogger<BackgroundWork> Logger
<button @onclick="LongRunningWork">Trigger long running work</button>
<button @onclick="Dispose">Trigger Disposal</button>
@code {
private Resource resource = new();
private CancellationTokenSource cts = new();
protected async Task LongRunningWork()
{
Logger.LogInformation("Long running work started");
await Task.Delay(5000, cts.Token);
cts.Token.ThrowIfCancellationRequested();
resource.BackgroundResourceMethod(Logger);
}
public void Dispose()
{
Logger.LogInformation("Executing Dispose");
cts.Cancel();
cts.Dispose();
resource?.Dispose();
}
private class Resource : IDisposable
{
private bool disposed;
public void BackgroundResourceMethod(ILogger<BackgroundWork> logger)
{
logger.LogInformation("BackgroundResourceMethod: Start method");
if (disposed)
{
logger.LogInformation("BackgroundResourceMethod: Disposed");
throw new ObjectDisposedException(nameof(Resource));
}
// Take action on the Resource
logger.LogInformation("BackgroundResourceMethod: Action on Resource");
}
public void Dispose()
{
disposed = true;
}
}
}
@page "/background-work"
@using System.Threading
@using Microsoft.Extensions.Logging
@implements IDisposable
@inject ILogger<BackgroundWork> Logger
<button @onclick="LongRunningWork">Trigger long running work</button>
<button @onclick="Dispose">Trigger Disposal</button>
@code {
private Resource resource = new();
private CancellationTokenSource cts = new();
protected async Task LongRunningWork()
{
Logger.LogInformation("Long running work started");
await Task.Delay(5000, cts.Token);
cts.Token.ThrowIfCancellationRequested();
resource.BackgroundResourceMethod(Logger);
}
public void Dispose()
{
Logger.LogInformation("Executing Dispose");
cts.Cancel();
cts.Dispose();
resource?.Dispose();
}
private class Resource : IDisposable
{
private bool disposed;
public void BackgroundResourceMethod(ILogger<BackgroundWork> logger)
{
logger.LogInformation("BackgroundResourceMethod: Start method");
if (disposed)
{
logger.LogInformation("BackgroundResourceMethod: Disposed");
throw new ObjectDisposedException(nameof(Resource));
}
// Take action on the Resource
logger.LogInformation("BackgroundResourceMethod: Action on Resource");
}
public void Dispose()
{
disposed = true;
}
}
}
@page "/background-work"
@using System.Threading
@using Microsoft.Extensions.Logging
@implements IDisposable
@inject ILogger<BackgroundWork> Logger
<button @onclick="LongRunningWork">Trigger long running work</button>
<button @onclick="Dispose">Trigger Disposal</button>
@code {
private Resource resource = new();
private CancellationTokenSource cts = new();
protected async Task LongRunningWork()
{
Logger.LogInformation("Long running work started");
await Task.Delay(5000, cts.Token);
cts.Token.ThrowIfCancellationRequested();
resource.BackgroundResourceMethod(Logger);
}
public void Dispose()
{
Logger.LogInformation("Executing Dispose");
cts.Cancel();
cts.Dispose();
resource?.Dispose();
}
private class Resource : IDisposable
{
private bool disposed;
public void BackgroundResourceMethod(ILogger<BackgroundWork> logger)
{
logger.LogInformation("BackgroundResourceMethod: Start method");
if (disposed)
{
logger.LogInformation("BackgroundResourceMethod: Disposed");
throw new ObjectDisposedException(nameof(Resource));
}
// Take action on the Resource
logger.LogInformation("BackgroundResourceMethod: Action on Resource");
}
public void Dispose()
{
disposed = true;
}
}
}
@page "/background-work"
@using System.Threading
@using Microsoft.Extensions.Logging
@implements IDisposable
@inject ILogger<BackgroundWork> Logger
<button @onclick="LongRunningWork">Trigger long running work</button>
<button @onclick="Dispose">Trigger Disposal</button>
@code {
private Resource resource = new Resource();
private CancellationTokenSource cts = new CancellationTokenSource();
protected async Task LongRunningWork()
{
Logger.LogInformation("Long running work started");
await Task.Delay(5000, cts.Token);
cts.Token.ThrowIfCancellationRequested();
resource.BackgroundResourceMethod(Logger);
}
public void Dispose()
{
Logger.LogInformation("Executing Dispose");
cts.Cancel();
cts.Dispose();
resource?.Dispose();
}
private class Resource : IDisposable
{
private bool disposed;
public void BackgroundResourceMethod(ILogger<BackgroundWork> logger)
{
logger.LogInformation("BackgroundResourceMethod: Start method");
if (disposed)
{
logger.LogInformation("BackgroundResourceMethod: Disposed");
throw new ObjectDisposedException(nameof(Resource));
}
// Take action on the Resource
logger.LogInformation("BackgroundResourceMethod: Action on Resource");
}
public void Dispose()
{
disposed = true;
}
}
}
Blazor Server yeniden bağlanma olayları
Bu makalede ele alınan bileşen yaşam döngüsü olayları, sunucu tarafı yeniden bağlantı olay işleyicilerinden ayrı olarak çalışır. İstemci bağlantısı SignalR kesildiğinde, yalnızca kullanıcı arabirimi güncelleştirmeleri kesilir. Bağlantı yeniden kurulduğunda kullanıcı arabirimi güncelleştirmeleri sürdürülür. Bağlantı hattı işleyicisi olayları ve yapılandırması hakkında daha fazla bilgi için bkz . ASP.NET Core BlazorSignalR kılavuzu.
Ek kaynaklar
Bir bileşenin Razor yaşam döngüsü dışında yakalanan özel durumları işleme
ASP.NET Core