2013-07-25 4 views
6

Jestem nowy w WCF. Wykonuję usługę, w której muszę obliczyć długą operację. Ponieważ metoda jest długa, pomyślałem, że mogę wykonać operację asynchroniczną, zwracając zadanie. Ale to nie działa. Nadal dostaję wyjątek Timeout. Przykładowy kod (nie mój rzeczywisty kod) wykazania mój problem poniżej:Metoda WCF ServiceContract powraca Zadanie <T> i limit czasu

[ServiceContract] 
public interface ICalculator 
{ 
    [OperationContract] 
    Task<double> ComputePiAsync(ulong numDecimals); 
} 

internal class Calculator : ICalculator 
{ 
    public async Task<double> ComputePiAsync(ulong numDecimals) 
    { 
     return await SomeVeryVeryLongWayOfComputingPi(numDecimals); 
    } 
} 

// server 
using (var host = new ServiceHost(typeof(Calculator), new Uri("net.pipe://localhost"))) 
{ 
    host.AddServiceEndpoint(typeof(ICalculator), new NetNamedPipeBinding(), "Calculator"); 
    host.Open(); 

    Console.WriteLine("Service is running. Press <ENTER> to exit."); 
    Console.ReadLine(); 

    host.Close(); 
} 

// client 
var factory = new ChannelFactory<ICalculator>(new NetNamedPipeBinding(), new EndpointAddress("net.pipe://localhost/Calculator")); 
var calculator = factory.CreateChannel(); 
await calculator.ComputePiAsync(numDecimals); // <--- this call takes longer than 1 minute and I'm getting a timeout here. 

Więc co należy zrobić, aby wywołać długie działanie na moją usługę i czekać na wynik asynchronicznie? Zwiększ limit czasu? Jeśli zwiększam limit czasu operacji, jaki jest sens, aby metoda zwróciła zadanie?

Odpowiedz

12

Ponieważ metoda jest długa Myślałem, że mogę zrobić operację asynchroniczny

trzymaj się, zwolnić - jesteś mieszania asynchrony z sieci limitu czasu pracy.

Pozwala rozważyć asynchrony pierwszy:

1. Korzystanie async/await do asynchronicznie połączenie usług WCF od klienta

async/await po stronie klienta pomaga nam napisać asynchroniczny program tak, że szczątki aplikacyjne responsywny - w przypadku np. WPF/WinForm nie chcemy zamrozić interfejsu użytkownika przez wywołanie usługi WCF synchronicznie w wątku interfejsu użytkownika. Zamiast tego możemy to nazwać asynchronicznie przy użyciu async/await. Magia polega na tym, że jest to pełna funkcjonalność po stronie klienta - co oznacza, że ​​usługa nie musi być asynchroniczna lub nie musi zwracać numeru Task - wszystko, co musisz, to podczas tworzenia musisz powiedzieć Visual Studio, aby wygenerować operacje asynchroniczne oparte na Task - a ty może następnie użyć klienta async/await.

2. W takim razie Jaka jest potrzeba dla async/await po stronie serwisu?

Sama usługa może wykonać pewne zapytanie, np. Niektóre źródła danych lub wywołać inną usługę. Korzystając z usługi async/await po stronie usługi - usługa może wykonywać te operacje asynchronicznie - bez blokowania żadnych wątków usługi. Co oznacza, że ​​serwis ma więcej darmowych wątków do obsługi nowych klientów - w związku z tym skala usług jest znacznie lepsza.

Teraz, powyżej dwóch nie należy mylić z długo działa operacja usługa

Kiedy usługa trwa długo, aby uzyskać wyniki, masz do czynienia z siecią timeout. Nie możesz i nie powinieneś próbować utrzymywać połączenia sieciowego bez końca, bez żadnej aktywności. WCF pomaga w tym, konfigurując różne limity czasu. Jeśli twoja metoda obsługi wymaga dużo czasu, musisz zwiększyć te limity czasu. Możesz rozważyć użycie WCF callback contracts, jeśli chcesz zgłosić postęp z powrotem do klienta.Jeśli to nie wystarcza, wymodeluj swoją usługę tak, aby klient mógł zainicjować długotrwały proces, a następnie wywołać inną metodę w usłudze, aby zapytać o status.

+3

+1. Aby wyjaśnić na ostatnim punkcie, 'async' po stronie serwera nie zwraca * do klienta * wcześniej. Odpowiedź jest wysyłana do klienta dopiero po zakończeniu zwróconego zadania. –

+1

@StephenCleary: Dzięki. Tak, asynchronizacja "async/await' po stronie usługi nie jest widoczna dla klienta. – YK1

+0

Cenne pytanie i dobra, jasna odpowiedź. Jeśli wywołanie jest długotrwałe, ponieważ operacja wymaga dużej ilości czasu obliczeniowego, nie jestem pewien, czy odwołałbym się do niej, powodując przekroczenie limitu czasu sieci. Wyobrażam sobie, że odnoszą się one do wysyłania/odbierania limitów czasu, podczas gdy limit czasu operacji odnosi się do tych czasów + obliczeń? –

0

Po pierwsze, musisz być pewien, że problem jest tak naprawdę wywołaniem asynchronicznym. Spróbuj połączyć się z usługą synchronicznie, aby sprawdzić, czy wywołanie odbywa się pomyślnie.

Zakładając, że Twój problem jest w rzeczywistości operacją asynchroniczną, powinieneś użyć WCF IAsyncResult zamiast async, ponieważ jest to domyślny sposób obsługi operacji asynchronicznych w WCF. Będziesz potrzebować operacji, aby rozpocząć usługę, a innej, aby przetworzyć wyniki.

mógłbym napisać trochę kodu, ale oto kilka dobrych stanowisk, które wyjaśniają, mój punkt widzenia w szczegółach i warto przeczytać:

Kolejna wskazówka:

Po wykonaniu tych kroków, jeśli okaże się, że klient potrzebuje więcej czasu na przetworzenie wykonanie asynchroniczny , należy rozważyć, aby zwiększyć operation timeout aby pozwolić dłużej czekać na powrót. Jeśli połączenie jest niestabilne, należy rozważyć zwiększenie wartości open timeout do , aby dać klientowi więcej czasu na nawiązanie połączenia.

Mam nadzieję, że to pomaga.