-2

I have a function that makes periodic checks to a web page (using REST) and then waits for a final response, if it gets a "non-final" response it tries again.

void PeriodicallyCheckSomething()
{
    Task.Run(() => {
        var isTaskComplete = false;
        while (!isTaskComplete)
        {
            CancellationToken.WaitHandle.Wait(5000);
            if (isTaskComplete || CancellationToken.IsCancellationRequested)
                return;

            CheckProgress((isComplete) => {
                isTaskComplete = isComplete;
                CancellationToken.WaitHandle.Set(); // <== can't do this
            });
        }
    });
}

// CheckProgress - exit's immediately, we use updateStatus to report the result

void CheckProgress(Action<bool> updateStatus)
{
    MakeWebRequest((data) => {
        var isComplete = (data.Result == 999);
        updateStatus(isComplete);
    });
}

I would like to exit the task cleanly. When I get a result I set the isTaskComplete flag, but the task is already in the wait state.

I would like to "Set" the Waithandle so that the Task immediately exits. However a CancellationToken.Waithandle doesn't have a Set function.

Is there a better way to Wait... that would support both Task Cancellation and the ability to signal it using something like Set?

Brian Rice
  • 3,107
  • 1
  • 35
  • 53
  • It is clear that the code you have is incorrect, but by that same virtue it is not clear what end result you want. For example, why are you doing anything with the cancellation token besides checking it? – theMayer Nov 21 '17 at 04:40
  • CancellationTokenSource.Cancel() gets called outside of this function. For example, if someone hit a cancel button on the UI. – Brian Rice Nov 21 '17 at 05:27
  • Yes, which is why the only thing you should do is check it. – theMayer Nov 21 '17 at 17:05
  • Can you please clarify the problem you are trying to solve? The code in your first method makes no sense... all I see is an infinite loop. What behavior are you trying for? Pseudocode would be fine or even just plain English. – theMayer Nov 21 '17 at 17:11
  • The first method loops until isTaskComplete is true... this would get set to true by the updateStatus callback in the CheckProgress function. – Brian Rice Nov 21 '17 at 20:52
  • which would happen if data.Result is equal to 999 – Brian Rice Nov 21 '17 at 20:53
  • I'm trying to get you to re-work the question so it is less reliant upon trying to get bad code to behave properly, and more clear on your requirements so you can get a good answer... clearly this is not working :( – theMayer Nov 21 '17 at 20:56

3 Answers3

0

Use Task.Delay to wait for the 5000ms. You can pass a CancellationToken to the Delay method through one of its overloads. I'm not seeing a reason why you need to track the concept of completion vs. cancellation. You simply want the task to end regardless.

Anthony T.
  • 268
  • 2
  • 11
0

I think what you need to do is fire off a Task, supplying it with a cancellation token and perform the wait 'outside' of the Task. Ie your PeriodicallyCheckSomething() method could be re-labeled as async and Task.Run from somewhere else. That somewhere else then can perform waits, etc. Just my 2c. Good luck

Monza
  • 745
  • 4
  • 12
0

What I did was make MakeWebRequest a blocking function.

void PeriodicallyCheckSomething()
{
    Task.Run(() => {
        var isTaskComplete = false;
        while (!isTaskComplete)
        {
            CancellationToken.WaitHandle.Wait(5000);
            if (CancellationToken.IsCancellationRequested)
                return;

            isTaskComplete = CheckProgress();
        }
    });
}

bool CheckProgress()
{
    var data = MakeWebRequest();
    return (data.Result == 999);
}
Brian Rice
  • 3,107
  • 1
  • 35
  • 53