0

I have a method that communicates with a HID device to retrieve a serial number, however the if the HID device is "present" but not active as is common when working with BT, the call for the serial will block and just sit there.

I would like to call my method but have it time out and return a empty serial if failed or the proper serial if successful.

Task.Run accomplishes most of this but does not kill the task if it hangs thus making my application impossible to exit.

        var task = Task.Run(() => GetSerialStringWorker(device));
        if (task.Wait(TimeSpan.FromMilliseconds(300)))
            return task.Result;
        else
        {
            //Need to be able to kill the task here!
            return "00:00:00:00:00:00";
        }

A cancellation token cannot be used either as the code that gets the serial is part of an external library and does not accept cancellation.

Also tried this, but it blocks on the thread.Join() and doesn't release properly when the thread is aborted;

        string sn = "00:00:00:00:00:00";
        System.Timers.Timer timeoutTimer = new System.Timers.Timer() { Interval = 300 };
        Thread thread = new Thread(() =>
        {
            sn = GetSerialStringWorker(device);
            timeoutTimer.Stop();
        });

        timeoutTimer.AutoReset = false;
        timeoutTimer.Elapsed += (s, e) => { thread.Abort(); };
        timeoutTimer.Start();

        thread.Start();
        thread.Join();
        return sn;

Ok so for whatever reason the Join in the above example keeps my application from fully loading and just sits there blocking the rest of the apps initialization. Solution was to block it using a while command;

        string sn = "";

        Thread thread = new Thread(() =>
        {
            sn = GetSerialStringWorker(device);
        });

        var timeoutTimer = new System.Threading.Timer((s) =>
        {
            thread.Abort();
            sn = "00:00:00:00:00:00";
        }, null, 500, Timeout.Infinite);

        thread.Start();
        while (sn == "")
        {
            Thread.Sleep(1);
        }
        return sn;

This feels really ugly but for now it works until somebody can figure out a better way.

Wobbles
  • 3,033
  • 1
  • 25
  • 51
  • Take a look at this answer: http://stackoverflow.com/a/11191070/959977 – OrangeKing89 Oct 28 '16 at 15:07
  • @OrangeKing89 As I said, Tasks do not allow abortion. – Wobbles Oct 28 '16 at 15:13
  • Maybe this approach can help? http://stackoverflow.com/a/32450407/635410 – Eldarien Oct 28 '16 at 15:25
  • @Eldarien That is very similar to what I am trying to do in my second example, I will have to compare and see why my still blocks. – Wobbles Oct 28 '16 at 15:27
  • 1
    I think you can replace the .Join() with an event mechanism. But Aborting threads is always doubtful regarding resources. – H H Oct 28 '16 at 15:29
  • 1
    maybe this will help http://stackoverflow.com/questions/2265412/set-timeout-to-an-operation – tym32167 Oct 28 '16 at 15:33
  • @HenkHolterman Agreed, but I gotta make due with what I have, unfortunately requesting a serial behaves in a way where they can block and not timeout on its own. – Wobbles Oct 28 '16 at 15:55
  • 1
    Because you are (apparently) dealing with third-party/unmanaged code, your options are limited. Aborting threads is a very bad idea, but so is leaving a thread active indefinitely for no good reason. See the marked duplicate for discussion on the poor options available to you. See also http://stackoverflow.com/questions/2781484/abort-call-to-unmanaged-dll for information on dealing with non-cancellable third-party calls. – Peter Duniho Oct 28 '16 at 18:10

1 Answers1

-1

Your problem seems to be that you want to cancel a non-cancelable async operation, take a look here for a possible technique to achieve that:

How do I cancel non-cancelable async operations

Also take a look at this answer https://stackoverflow.com/a/14524565/7070657

Community
  • 1
  • 1
brakeroo
  • 1,407
  • 13
  • 24