Nie można zaktualizować interfejs użytkownika po zakończeniu zadania w tle w moim ASP.NET zastosowanie

0

Pytanie

Uruchamiam długą funkcję jako zadania w tle w swoim asp.net zastosowanie. Przed zakończeniem zadania głównego wątku (chcę, aby to było tylko tak, ponieważ, jeśli używam słowa kluczowego await i sprawię, że główny wątek czekać na zakończenie zadania w tle, otrzymam komunikat o błędzie serwera proxy

Błąd serwera proxy
Proxy-serwer otrzymał błędną odpowiedź od nadrzędnego serwera, tak jak w tle zadaniem zbyt długa

Ale po zakończeniu zadania ani nie mogę zaktualizować stronę, aby przekierować ją na tej samej stronie, ani ja nie mogę zastąpić interfejs użytkownika. Czy jest jakiś sposób zaktualizować interfejs użytkownika po zakończeniu wykonywania głównego wątku.

Mój kod brzmi tak:

protected void btnImport_Click(object sender, EventArgs e)
{
        var task = ImportThread();

        if (task.IsCompleted)
        {
            DisplaySuccess("Import success");
        }
        else
            DisplayError("Import failed");
}

private async Task<bool> ImportThread()
{
        try
        {
            var success = await Task<bool>.Run(() => new Manager().Import().ConfigureAwait(false);

            if (task.IsCompleted)
            {
                DisplaySuccess("Import success");
            }
            else 
            {
                DisplayError("Import failed");
            }
    
            return true;
}

Opisane powyżej zadanie asynchroniczne czeka metody opisanej poniżej, który jest obecny w innej klasie.

public bool Import()
{
    // some operations here
    return true;
}

Po zakończeniu tej metody, sterowanie jest zwracane w ImportThread() ale kod napisany tam do zastępowania interfejsu użytkownika, nie aktualizuje interfejs użytkownika. Muszę zaktualizować interfejs użytkownika ze statusem importu. A także od ImportThread sterowanie również nie wraca do metody zdarzenia naciśnięcia przycisku.

Proszę, pomóż mi w jakikolwiek sposób zaktualizować interfejs użytkownika statusu importu.

Uwaga: próbowałem użyć Redirect.Response w ImportThread() aby odświeżyć stronę, ale to nie zadziałało

asp.net async-await background-task c#
2021-11-23 19:55:22
2

Najlepsza odpowiedź

1

Problem w tym, że trzeba zrozumieć i zrozumieć cykl życia strony internetowej tutaj.

Masz ten przypadek, gdy strona znajduje się na pulpicie użytkownika:

enter image description here

Teraz załóżmy, że użytkownik kliknie przycisk.

Teraz masz to:

 var task = ImportThread();

    if (task.IsCompleted)

Tak więc, strona otwarta na serwerze. Możesz włączyć nawet asynchroniczne czekam, aż krowy nie wrócą do domu, ale NADAL MASZ TO:

enter image description here

W ten sposób, tak długo, jak twój kod działa lub oczekuje, strona NADAL ZNAJDUJE się na stronie serwera. TYLKO do momentu, dopóki kod nie zakończy się i nie zakończy się, strona przechodzi na stronę klienta.

ponownie: Twój kod nie może się zatrzymać i nie może czekać, aż coś się zakończy, ponieważ jeśli tak się stanie, to strona ZOSTANIE na serwerze, aż do zakończenia przetwarzania.

WTEDY I TYLKO WTEDY, gdy strona wraca na stronę klienta. Następnie to się dzieje;

enter image description here

A następnie STRONA po STRONIE SERWERA WYRZUCA się Z pamięci, a wszystkie zmienne klasy ZNISZCZONE!!! Serwer teraz czeka, gdy KAŻDY UŻYTKOWNIK wyśle z powrotem stronę do obróbki!!

Tak więc, jeśli trzeba uruchomić jakiś długi proces?

Masz kilka opcji:

opublikuj stronę, kod z tyłu uruchamia kod za uruchamia NOWY wątek, strona wraca na stronę klienta. W tym momencie potrzebny jest zegar + jakiś typ połączenia sieci-metody (ajax), aby zadać pytanie lub poprosić serwer, zakończona czy długi proces. I ponieważ wywołanie ajax nie korzysta z żadnych stron-elementów sterowania na tej stronie lub zmiennych klasy strony (pamiętaj, ŻE PO tym, jak strona zostanie przeniesiona z powrotem na stronę klienta, strona NIE JEST NIEISTNIEJĄCEGO po stronie serwera www w pamięci, i żadna ze zmiennych klasy nie istnieje). Tak więc, ponownie, jest to w dużej mierze oznacza jakiś timer lub, jak już wspomniano, kod czasowy + do wywołania jakiejkolwiek metody ajax. i tego długotrwałego procesu, najprawdopodobniej, będzie musiał użyć session (), tak jak nie używasz elementy sterowania lub nawet stan wyświetlania.

I nie musisz korzystać z ajax. Można użyć prostą procedurę po stronie klienta JavaScript z zegarem, który mówi, że kliknie przycisk co 1 lub 2 sekundy, kod jest uruchamiany, a następnie będzie musiał uzyskać status tego długotrwałego procesu (znowu, prawdopodobnie z sesji), a następnie uaktualnić ekran. A następnie można również włączyć kod, aby zatrzymać stoper, gdy status zmieni się na "gotowe" lub coś innego.

W ten sposób kod, leżący w oparciu o nie "aktualizuje" stronę i nie będzie "aktualizować" ją kilka razy. Masz JEDNĄ podróż tam i z powrotem, i kod, leżący w bazie, musi działać szybko, musi się skończyć, i nie można nawet użyć polecenia "CZEKAĆ", tak jak wtedy strona będzie czekać, a i tak utknie na serwerze.

Jeśli chcesz wyjść poza proste podejście z zegarem, który często używam?

Następnie trzeba podjąć i wdrożyć na swojej stronie internetowej, że to, przeznaczony do tego typu przypadków -

Na szczęście do tego celu istnieje SignalR, i jest to bez wątpienia najlepsze rozwiązanie i podejście dla ciebie, ponieważ jest on zaprojektowany właśnie do twojego pytania i scenariusza.

СигналР

https://docs.microsoft.com/en-us/aspnet/signalr/overview/getting-started/introduction-to-signalr#:~:text=What%20is%20SignalR%3F%20ASP.NET%20SignalR%20is%20a%20library,process%20of%20adding%20real-time%20web%20functionality%20to%20applications.

2021-11-23 21:28:35
0

Jeśli chcesz asynchronicznie powiadomić użytkownika o zakończeniu lub awarii czegokolwiek, np. zadania), można korzystać z sieci-push-powiadomienia (z pomocą firebase cloud messaging) lub gniazda SignalR. Gdy używasz zadania w tle, tracisz główny wątek, i, niestety, nie ma możliwości odpowiedzieć odpowiedniego użytkownika.

2021-11-23 20:31:11

W innych językach

Ta strona jest w innych językach

Русский
..................................................................................................................
Italiano
..................................................................................................................
Română
..................................................................................................................
한국어
..................................................................................................................
हिन्दी
..................................................................................................................
Français
..................................................................................................................
Türk
..................................................................................................................
Česk
..................................................................................................................
Português
..................................................................................................................
ไทย
..................................................................................................................
中文
..................................................................................................................
Español
..................................................................................................................
Slovenský
..................................................................................................................