2015-04-06 23 views
8

Używam wywołań asynchronicznych WCF w moim projekcie i używam metod asynchronicznych po stronie klienta. Mam scenariusz jak poniżej -Jak rzucić wyjątek od wywołania zwrotnego w WCF Async przy użyciu IAsyncResult

//Code in Business Layer and this method is called from Web layer 
    private void GetGeneralNews() 
    { 
     client.BeginGetGeneralNewsFeed(GeneralNewsCallback, null); 
    } 

    //Call Back Method 
    private static void GeneralNewsCallback(IAsyncResult asyncResult) 
    { 
     string response = string.Empty; 

     try 
     { 
      response = client.EndGetGeneralNewsFeed(asyncResult); 
     } 
     catch(Exception ex) 
     { 
      throw ex; // Here is the problem. It does not throw the exception to the web layer instead it will suppress the error. 
     } 
    } 

Tak jak pokazano w powyższym fragmencie kodu nie rzucać wyjątek od warstwy biznesowej do warstwy internetowej, jak to będzie tłumione tutaj w samej warstwie biznesowej.

Sprawdziłem niektóre blogi i witryny, które sugerują, aby przejść do asynchronizacji i oczekują na podejście, ponieważ mam framework .NET 4.0 i widzę "" Opcja "Operacje oparte na zadaniach" została wyłączona. Więc jeśli są jakieś opcje przy użyciu "IAsyncResult" (Begin & Koniec po stronie klienta), proszę dać mi znać. Jeśli są inne podejścia, również mile widziane.

Uprzejmie, proszę, pomóż mi.

Dzięki.

+0

Sprawdź, czy link może być pomocny http://blogs.msdn.com/b/nikos/archive/2011/03/14/how-to-implement-iasyncresult-in-another-way.aspx#comments – reapen

+0

mówisz, że twój blok "catch" nie wychwytuje żadnego wyjątku? Jeśli nieobsługiwany wyjątek zostanie zgłoszony w kodzie po stronie serwera, powyższy blok 'catch' powinien domyślnie przechwycić wyjątek" FaultException ". –

+0

A więc chcesz, aby wyjątek zadzwonił do dzwoniącego, gdy dzwoni do "GetGeneralNews"? – usr

Odpowiedz

0

mimo to rozwiązać to za pomocą TPL (Task Parallel Library).

Powód, dla którego pojawiały się problemy w powyższym podejściu, moje nowe wątki nie będą w stanie rozpoznać głównego wątku, od którego warstwa została wywołana.Tak więc używanie TPL i sprawiło, że mój główny wątek czekał, aż moje inne wątki wykonają zadanie i wrócą, a następnie na podstawie odpowiedzi rzucają wyjątek.

Mam nadzieję, że to pomaga.

0

1) Jeśli już wygenerowałeś kod klienta WCF za pomocą metod asynchronicznych ("Rozpocznij ..."/"Zakończ ...") - możesz użyć interfejsu API zadania TPL do pracy z WCF (ContinueWith itp.) Przez Task.Factory.FromAsync (example) - dobre do radzenia sobie ze starszymi metodami IAsyncResult ("Begin ..."/"End ...")/API (choć proste, widać źródło z reflektorem);

2) Generowany narzę dzie kod klienta nie jest dobrym rozwiĘ ... zaniem - zamiast tego można napisać własny uniwersalny klient-proxy z obsługĘ ... prawdziwego asynchronizujĘ ... cego (a nie tylko z gwintem tle). Here to dobry przykład, jak zacząć, musisz zawijać metody "Rozpocznij ..."/"Zakończ ..." metodami opartymi na zadaniach (użyj tego samego Task.Factory.FromAsync) i użyj drzewek wyrażeń, aby pozbyć się metody obsługi opartej na łańcuchach połączeń (nie mogę udostępnić źródła mojej klasy).

Lub możesz użyć istniejących rozwiązań, takich jak this.

3) Nie zapomnij o ConfigureAwait.

Edit:

Nie trzeba generować operacje oparte na zadaniach, to wystarczy, aby wygenerować kod klienta WCF z metod operacyjnych usług asynchroniczny („Begin ...”/„Koniec ...”). Lub możesz mieć tylko synchroniczną umowę WCF! (patrz linki). TPL dostępne w .NET 4 (bez asynchronicznego/czekającego syntaktycznego cukru - czyli funkcja językowa CSharp 5.0). Użyj go (ContinueWith zamiast czekać na + When Any, WhenAll). Użyłem go nawet w 3.5 przez Microsoft Reactive Extensions v1.0.2856.0. AFAIK Reactive Extensions był początkową wersją, która została uwzględniona w BCL. ParallelExtensionsExtras może być również użyteczny

+0

Jak już wspomniałem "Generowanie operacji opartych na zadaniach" będzie dostępne tylko w wersji 4.5 .NET. Więc nie mam tutaj tej opcji. –

+0

Nie musisz. Zobacz edytowaną odpowiedź. Przeczytaj uważnie. – SalientBrain

+0

Prosimy o rozważenie dodania komentarza po zgłoszeniu. – SalientBrain

2

Oto przykładowa aplikacja, która pokazuje, że WCF nie połyka wyjątku. Jeśli nie otrzymasz wyjątku, musi zostać połknięty przez kod po stronie serwera.

using System; 
using System.ServiceModel; 
using System.ServiceModel.Description; 
using WcfQ.QServiceReference; 

namespace WcfQ 
{ 
[ServiceBehavior(IncludeExceptionDetailInFaults = true)] 
public class QService : IQService 
{ 
    public void Foo() 
    { 
     throw new ApplicationException("Please catch this"); 
    } 
} 

[ServiceContract] 
public interface IQService 
{ 
    [OperationContract] 
    void Foo(); 
} 

class Program 
{ 
    static private QServiceClient client; 

    static void Main(string[] args) 
    { 
     ServiceHost host = new ServiceHost(typeof(QService), new Uri("http://localhost:20001/q")); 
     AddWsdlSupport(host); 
     host.AddServiceEndpoint(typeof (IQService), new WSHttpBinding(SecurityMode.None), ""); 
     host.Open(); 

     client = new QServiceClient(); 
     client.BeginFoo(FooCallback, null); 
     Console.WriteLine("ready"); 
     Console.ReadKey(); 
    } 

    private static void FooCallback(IAsyncResult asyncResult) 
    { 
     try 
     { 
      client.EndFoo(asyncResult); 
     } 
     catch (Exception ex) 
     { 
      Console.WriteLine("Got the exception: " + ex.Message); 
     } 
    } 

    static void AddWsdlSupport(ServiceHost svcHost) 
    { 
     ServiceMetadataBehavior smb = svcHost.Description.Behaviors.Find<ServiceMetadataBehavior>(); 
     // If not, add one 
     if (smb == null) 
      smb = new ServiceMetadataBehavior(); 
     smb.HttpGetEnabled = true; 
     smb.MetadataExporter.PolicyVersion = PolicyVersion.Policy15; 
     svcHost.Description.Behaviors.Add(smb); 
     // Add MEX endpoint 
     svcHost.AddServiceEndpoint(
      ServiceMetadataBehavior.MexContractName, 
      MetadataExchangeBindings.CreateMexHttpBinding(), 
      "mex" 
     ); 

    } 
} 

}

Tutaj jest wyjście z tego programu:

ready 
Got the exception: Please catch this