C# API Hardware – Avoiding Hangs When Calling a Native API

apichardwarenativewrapper

Background

We have a piece of programmable hardware here at work that we integrate into almost all of our systems. This piece of hardware came with a native Windows DLL (for which we do not have the source code) as well as a wrapper to said library. This wrapper is responsible only for marshalling the calls to the native API up to the .NET layer and nothing more. Therefore, we use this wrapper in order to make the calls to the native API.

This piece of programmable hardware is physically integrated into our product in a very problematic way. The piece of hardware sits in the product in such a way that every once in a while the USB cable gets cut in half… (don't ask) The problem is that the cable tends to get cut in half when we are deep into the native API. When this happens, the caller will not return from the native API function. Below is a snippet of what the call looks like via the wrapper:

    public static UInt32 Wrap(UInt32 configval, Int32 channum, IntPtr handleval)
    {
        if (IntPtr.Size == 4)
            return Native32(configval, channum, handleval);
        else
            return Native64(configval, channum, handleval);
    }

Question

Is there a general method of making sure we don't hang inside of the API?

I already know that I can just start a task, and wait for it with a timeout (just resume if it times out). This method works, but is there any other way of doing this? I have no control whatsoever of what goes on inside the API.

Best Answer

Basically the problem is blocking on a call that will never return. This is a solved problem in that every network call is highly likely to fail so we have things like sockets that have timeouts built-in to them. In one sense, the problem is that your code assumes this won't fail to respond when it can. The only way to get around that is to stop blocking on that call. You'll need some sort of asynchronous capability. Whether you use some sort of non-blocking IO or spawn a thread, the solution will have the same kind of high-level design.

The solution depends a lot on the overall architecture. If you are structured around a work-queue, then the nicest solution is when the API returns (or times out) you push the response to the work queue and deal with it. On the other hand, if your application is highly sequential, you probably have to block the main thread until the response comes back (or times out.)

In either approach, one issue is how long the API can be expected to take. If the response time is highly regular (low variance) then you can simply accept the timeout as a failure. If you can't put a reasonable upper-limit on the response time, you might want to take one more step on timeout to send another request to the API (preferably something fast) to check whether you are still connected. If you are still able to connect, the cord isn't cut and you can wait some more and repeat as necessary.

Related Topic