2010-05-11 15 views
10

Mam stronę internetową asp.net (mvc). Jako część funkcji będę musiał obsługiwać długo działające operacje, na przykład:Długie operacje (wątki) w środowisku sieciowym (asp.net)

Zainicjowany przez użytkownika: Użytkownik może przesłać (xml) plik na serwer. Na serwerze muszę wyodrębnić plik, wykonać trochę manipulacji (wstawić do bazy danych) itd. Może to potrwać od jednej minuty do dziesięciu minut (lub nawet więcej - w zależności od rozmiaru pliku). Oczywiście nie chcę blokować żądania, gdy import jest uruchomiony, ale chcę przekierować użytkownika na stronę postępu, na której będzie mógł zobaczyć status, błędy, a nawet anulować import.

Ta operacja nie będzie często używana, ale może się zdarzyć, że dwóch użytkowników jednocześnie spróbuje zaimportować dane. Byłoby miło równolegle zarządzać importem. Na początku zastanawiałem się nad stworzeniem nowego wątku w iis (działanie kontrolera) i uruchomiłem import w nowym wątku. Ale nie jestem pewien, czy to dobry pomysł (aby stworzyć działające wątki na serwerze WWW). Czy powinienem używać usług Windows lub innego podejścia?

Zainicjowany z systemu: - Będę musiał okresowo aktualizować wskaźnik lucenu o nowe dane. - Będę musiał wysłać masowe wiadomości e-mail (w przyszłości).

Czy powinienem wdrożyć to jako zadanie na stronie i uruchomić zlecenie za pośrednictwem Quartz.net, czy też powinienem utworzyć usługę Windows czy coś?

Jakie są najlepsze praktyki, jeśli chodzi o uruchamianie witryny "oferty pracy"?

Dzięki!

+0

Rozważ niektóre z odpowiedzi na powiązane pytanie http://stackoverflow.com/a/41734936/56145 –

Odpowiedz

6

Wdrożę samodzielną usługę okien dla długotrwałych zadań. Aplikacja sieci Web deleguje długoterminowe zadania do tej usługi za pomocą podejścia kolejkowego. To od Ciebie zależy, jak zorganizujesz kolejkę zadań. Zadanie w kolejce ma priorytet, maksymalny czas wykonania lub nie. Kolejka może być zaimplementowana jako zwykła tabela (tabele) w systemie DBMS, która zawiera właściwości informacji o statusie wykonania zadania (dość proste podejście).

tak powszechny scenariusz może wyglądać następujące:

  • Klient wysyła wszystkie wymagane informacje do serwera WWW

  • zadanie delegaci Web-serwer do obsługi i powiadomi klienta - zadanie zostało powodzeniem kolejce (identyfikator zadania jest wysyłany również do klienta)

  • Usługa zewnętrzna rozpoczyna przetwarzanie zadań, aktualizowanie informacji o postępach n.

  • Klient uruchamia serwer pollingu z krótkimi żądaniami wykonania zadania (z wcześniej otrzymanym id) stan i postęp.

Można wybrać różne technologie (Windows Usługa + db/WCF Service) oraz różnych metod komunikacji (ankietowanie, pchanie, wywołania zwrotne), ale radzę powierzyć długo uruchomionych zadań do usługi zewnętrznej (nie wykonywać ich w internecie aplikacja).

Wykonywanie zadań długotrwałych przynosi model wątku na żądanie (w terminologii programowania wielowątkowego). Model ten ma słabą skalowalność i maksymalną liczbę ograniczeń wątków w puli wątków. To jednak nie twoja sprawa :)

+0

Zwykle robiłem duże konwersje, generowanie raportów, generowanie danych w taki sposób. To jedyny logiczny wybór. –

4

Moim zdaniem długotrwałe zadania powinny zawsze być zawsze delegowane do operacji nie opartych na interfejsie użytkownika. Sugerowałbym być może usługę WF lub Window.

1

Pomyślnie zaimplementowałem scenariusz podobny do tego przy użyciu jQuery. zasadniczo używam funkcji beforeSend :, aby wyświetlić stronę typu "proszę czekać". Oto kod podstawowy w grze (altso ja nie, można również użyć klasy AsyncController bazową aby asynchronicznie działania):

<script type="text/javascript"> 
    $(document).ready(function() { 
     $('#create').bind('click', function() { 
      saveFundProperty(); 
     }); 
    }); 

    // main functions 
    function saveFundProperty() { 
     var url = '<%= Url.Action("Create", "FundProperty") %>'; 
     var params = { fundId: $("#FundID").val(), propertyId: $("#PropertyID").val() }; 
     SendAjax(url, params, beforeQuery, saveFundPropertyResponse); 
    } 

    function beforeQuery() { 
     var url = '<%= Url.Action("Wait", "FundProperty") %>'; 
     $("#statusMsg").load(url); 
    } 

    function saveFundPropertyResponse(data) { 
     if (data.length != 0) { 
      if (data.indexOf("ERROR:") >= 0) { 
       $("#statusMsg").html(data).css('backgroundColor','#eeaa00'); 
      } 
      else { 
       $("#statusMsg").html(data); 
      } 
     } 
    } 
</script> 

nadzieję, że to pomaga.

Metoda jest czysto opakowującą funkcją, która sprawia, że ​​wszystko jest bardziej spójne. tutaj jest w całości:

<script type="text/javascript"> 
function SendAjax(urlMethod, jsonData, beforeSendFunction, returnFunction, dataType, contentType) { 
    $.ajaxSetup({ cache: false }); 
    dataType = dataType || "text"; // default return type 
    contentType = contentType || "application/x-www-form-urlencoded"; // default input type 
    $.ajax({ 
     type: "POST", 
     url: urlMethod, 
     data: jsonData, 
     dataType: dataType, 
     contentType: contentType, 
     beforeSend: function() { 
      if(beforeSendFunction!==null) 
       beforeSendFunction(); 
     }, 
     success: function(data) { 
      // Do something interesting here. 
      if (data != null && returnFunction!==null) { 
       returnFunction(data); 
      } 
     }, 
     error: function(xhr, status, error) { 
      // Boil the ASP.NET AJAX error down to JSON. 
      var err = eval("(" + xhr.responseText + ")"); 

      // Display the specific error raised by the server 
      alert(err.Message); 
     } 
    }); 
} 
</script> 

[edycja] - nie wiem, co dzieje się z formatowaniem SendAjax. mam nadzieję, że łatwo je skopiować/wkleić ...