简体   繁体   中英

How can I give a WCF service more time to complete after it times out?

We have a long-running asynchronous WCF service operation that grabs log files from the different components in our service. Right now, everything works correctly, but there's one more "nice to have" feature we'd like to implement.

WCF will time out asynchronous services if they take too long, but if one of our components is misbehaving, it could take a longer to give out its log file than we allot for the timeout period. If this happens, it would be nice if the client application told the user that getting log files was taking a while and asked if the user wanted to keep on waiting. If the user says yes, is there some way to resume the operation in the state it was when it timed out and reset the timeout timer?

This psuedocode shows what we have in mind:

public void GetServiceLogFiles(Action<Object> callback)
{
    try
    {
        var gotLogFilesDelegate = (result) =>
            { var answer = WcfService.EndGetLogFiles(result);
              callback(answer); };
        WcfService.BeginGetLogFiles(gotLogFilesDelegate, null);
    }
    catch(TimeoutException)
    {
        var dialog = new Dialog("The service is taking a while to get the log files. Would you like to keep on waiting for it to finish?");
        if(dialog.response = Dialog.YES)
            Magic_happens_here_and_lets_the_Wcf_Service_continue_working_on_Get_Log_Files();
    }
}

There is a way to set the timeout values. Take a look at System.ServiceModel.Channels.Binding, which has the following properties:

ReceiveTimeout
OpenTimeout
SendTimeout
CloseTimeout

These can be set when creating a service proxy.

public static class MyWcfServiceProxyFactory
{
    public static MyWcfService CreateMyWcfService(string endpointUrl) 
    {

        EndpointAddress endpointAddress = new EndpointAddress(endpointUrl);
        CustomBinding customBinding = new CustomBinding();

        TimeSpan timeout = new TimeSpan(0, 5, 0);

        customBinding.ReceiveTimeout = timeout;
        customBinding.OpenTimeout = timeout;
        customBinding.SendTimeout = timeout;
        customBinding.CloseTimeout = timeout;

        ChannelFactory<MyWcfService> channelFactory = new ChannelFactory<MyWcfService>(customBinding, endpointAddress);

        return channelFactory.CreateChannel();
    }
}

The same settings are available if the binding is creating in config.

<bindings>
    <basicHttpBinding>
        <binding name="MyWcfService"  
        receiveTimeout="0:05:00"
        openTimeout="0:05:00"
        sendTimeout="0:05:00"
        closeTimeout="0:05:00">

I do not think the timeout can be changed after the fact, so you will have to create 2 channels, one with the "normal" timeout, and one with an extended timeout. If the normal one times out, the retry attempt can use the channel with the extended timeout.

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