Click here to Skip to main content
14,979,837 members
Articles / Programming Languages / C#
Tip/Trick
Posted 18 Mar 2020

Tagged as

Stats

6.8K views
162 downloads
4 bookmarked

Timeout for Functions

Rate me:
Please Sign up or sign in to vote.
4.76/5 (11 votes)
18 Mar 2020CPOL2 min read
A short utility class implementing a timeout for functions
In this tip, you will see a couple of examples for how to add time out for functions that may just hang.

Introduction

When communicating with external services, some functions may just "hang": attempting to establish a TCP connection when the network or the other device is down takes 21s till you get a failure message. When the device is in your local network, you can normally be sure to get the connection within less than a second or not at all, and there is no need to waste so much time.

So it’s appropriate to add some time out. There are a couple of examples how to achieve that, but they require the repetition of (short) boiler plate code.

Thanks to generics and functional features of C# that can be encapsulated.

The Code

We need three items:

  • A function to execute
  • The timeout for that function
  • A function to execute in case of the timeout

The first step is to start a Task with the function. Task has a Wait(TimeSpan timeout) function, which returns true if the task completed in time. Here, we can return the Result property of the task. Otherwise, we execute the onTimeout function and return its result.

The code is simple:

C#
public static T Execute(Func<t> function, TimeSpan timeout, Func<t> onTimeout)
{
    Task<t> task = Task.Run(function);
    if (task.Wait(timeout))
    {
        // the function returned in time
        return task.Result;
    }
    else
    {
        // the function takes longer than the timeout
        return onTimeout();
    }
}

Instead of returning a default value, you may also throw an exception in the onTimeout function.

Unfortunately, in C# Function is a concept different from Action. Hence, I added an overload for Action, too.

Limitation: Cancellation

As you may find out, the original function stays alive after timeout - it continues to hang till it has run to completion. With the example of the TCP connection, that does not matter. If it consumes valuable ressources like CPU, that's bad.

Task.Run has an overload which takes a CancellationToken. But that does not help when the original function does not support cancellation (it must check the IsCancellationRequested property of the CancellationToken). If it does, you do not need this code, just supply a new CancellationTokenSource(timeout).Token to it.

This is a limitation for the use of this code.

Using the Code

Let’s add some examples.
I created a function which sleeps for a day before returning true – that corresponds to the „hanging“ function.

In the default value example, I set up 3 variables for the 3 items:

C#
Func<bool> theFunction = DoSomething;
TimeSpan timeout = TimeSpan.FromSeconds(3);
Func<bool> onTimeout = () =>
{
    // Log the timeout
    // Logger.Log("A timeout occurred");
    // then return a default value
    return false;
};

and then execute it:

C#
bool success = TimedExecution<bool>.Execute(theFunction, timeout, onTimeout);

but you could write it more concisely, too:

C#
bool success = TimedExecution<bool>.Execute(DoSomething, TimeSpan.FromSeconds(3), () => false);

The exceptional example works analogous. Here, the onTimeout function is set up to throw an exception:

C#
Func<bool> onTimeout = () =>
{
    // in this scenario, we want to receive an exception
    throw new TimeoutException("The function was to slow.");
};

In the example code, I added [TestMethod] attributes, which allow for executing and debugging these example functions from Visual Studio.

Points of Interest

You can now adjust the functions to your typical needs. Example, you might log the timeout directly in the Execute function. Or you only need a function which always throws a TimeoutException in case of timeout. Or whatever fits your requirements best. Now it's centralized and you can change the behavior at a single point.

History

  • 18th March, 2020: First version
  • 20th March, 2020: Added more info on the background, and the limitations for the use of the code

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Bernhard Hiller
Software Developer (Senior)
Germany Germany
No Biography provided

Comments and Discussions

 
QuestionConversion to VB.net Pin
Padanian19-Mar-20 3:27
MemberPadanian19-Mar-20 3:27 
QuestionTimed Out Method Runs to Completion. Pin
George Swan18-Mar-20 20:46
MemberGeorge Swan18-Mar-20 20:46 
AnswerRe: Timed Out Method Runs to Completion. Pin
57thStIncident19-Mar-20 10:23
Member57thStIncident19-Mar-20 10:23 
GeneralRe: Timed Out Method Runs to Completion. Pin
George Swan19-Mar-20 22:08
MemberGeorge Swan19-Mar-20 22:08 
AnswerRe: Timed Out Method Runs to Completion. Pin
Bernhard Hiller19-Mar-20 22:54
MemberBernhard Hiller19-Mar-20 22:54 
QuestionNot sure ... Pin
User 1106097918-Mar-20 12:02
MemberUser 1106097918-Mar-20 12:02 
AnswerRe: Not sure ... Pin
Bernhard Hiller19-Mar-20 22:51
MemberBernhard Hiller19-Mar-20 22:51 
GeneralRe: Not sure ... Pin
User 1106097919-Mar-20 23:21
MemberUser 1106097919-Mar-20 23:21 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.