简体   繁体   中英

What to do with a WCF service client in faulted state?

I consume a WCF service asynchronously . If I can't connect to the service or an exception occurs it went to faulted state and it writes the error to the Error property of the AsyncCompletedEventArgs .

What do I have to do with the service client? I cannot close it because it would throw a CommunicationObjectFaultedException . What else do I have to do after logging the error?

Here's my code:

MyServiceClient serviceClient = new MyServiceClient();

//Close the connection with the Service or log an error
serviceClient.JustAMethod += (object sender, AsyncCompletedEventArgs args) =>
{
    if (args.Error != null)
    {
        //Log error
        ErrorHandler.Log(args.Error);
    }
    else
    {
        serviceClient.Close();
    }
};

//Call the service
serviceClient.JustAMethodAsync();

You can abort it, and create a new one. Here's a fragment from a class I wrote that deals with that issue. Everything that it touches here is legal to touch when the client is in the faulted state.

if (_client.InnerChannel.State == CommunicationState.Faulted)
{
    _client.Abort();
    _client = new TServiceClient();
}

TServiceClient is any subclass of System.ServiceModel.ClientBase<TIClientInterface> .

I wrote that because I've had constant access issues calling webservices from the server end of an MVC4 web app, with the browser client accessing the page via RDS.

However, as of now, the above code isn't in use. For reasons I don't understand, it had a lot more access-denied exceptions than the simplest approach of invariably creating a new client for every call, and disposing it after. I never bother checking faulted state because I never use them for more than one call anyway.

using (var cli = new Blah.Blah.FooWCFClient())
{
    _stuff = cli.GetStuff();
}

...in a try/catch, of course. If you see any issues with the client-caching/Abort approach, I'd suggest you try creating a new client for every call. Maybe it costs a few cycles, but it's silly to call a web service and then start worrying about runtime efficiency. That horse has left the barn.

I don't know how this would interact with the asynchronous business, other than a vague intuition about keeping things simple and not sharing anything across threads.

Welcome to my nightmare. I haven't yet identified the cause of our access issues, but I doubt things can possibly be that bad for you. So I hope at least one of those two options will work out.

UPDATE

Here's some .tt-generated service wrapper code from our XAML application. Every web service call method gets wrapped like this, and it's been bulletproof for years. I would recommend doing essentially this:

public static POCO.Thing GetThing(int thingID)
{
    var proxy = ServiceFactory.CreateNewFooWCFClientInstance();
    try
    {
        var returnValue = proxy.GetThing(thingID);
        proxy.Close();
        return returnValue;
    }
    catch(Exception ex)
    {
        //  ***********************************
        //  Error logging boilerplate redacted
        //  ***********************************
        proxy.Abort();
        throw;
    }
}

I have a feeling that it's just as well if you don't reuse WCF client objects at all.

There is not much you can do with it. Create a new one and let the garbage collector collect the other one.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM