Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

New Methods: Implementing INFINITE LOOP which can be STOPPED upon request

What is the correct method to implement a infinitely running task which executes an Async BigJob()? and can be stopped upon request

Hint: I am trying to learn [a] new method(s) to update my existing strategy.

I have this simple program (a tester) which has an Start and Stop button.

When Start pressed, I am starting the tester which is going to find and test available devices in range and test the hell our of them in infinite amount of rounds until the user presses the Stop button.

The important point is, the main process/action/bigJob() is and awaitble asynchronous process.

So I would pseudo code the whole thing as

Start
  Round 1 starts
    Async Main job starts
       Async connect
       Async Read
       Async Write
       Async disconnect 
    Nobody cancelled me yet
  Round 1 finishes
  Round 2 starts
    .
    .
    .
  Round 2 finishes
  Round 3 starts
    .
    Stop pressed, hence break out. 
Stop

So I am using BackgroundWorker to implement the infinite loop and Async/Await for the Connect, read, write and disconnect that I have written in C# under .Net 4.5

Since my sub-tasks such as Connect and .etc are async then my main task is async and pressing the Stop button stops my process since it eliminates the infinite while loop that I have with having

while (!bw.CancellationPending)
{
    await MainTask();
    ...
}

but it doesn't fire the BackgroundWorker_RunWorkerCompleted event, which doesn't do me any harm HOWEVER it's killing me since the background worker doesn't work as it's supposed to and I just keep thinking "there should be a better way!".

So, I have been reading about so many new ideas, like why to use BackgroundWorker at all now that we have Async/await. Some were saying use Task.Run() it's magical. I even read recommendations and blogs about this godsend TPL Dataflow that I have never heard of. And so far I haven't found a method which is as structured, documented and layed-out as a BackgroundWorker. (unless it's such simple or a one liner which doesn't even need documentation or .etc) So, guys, what is the solution for this. Or better way to ask:

What is the correct method to implement a infinitely running task which executes an Async BigJob()? and can be stopped upon request

like image 434
Mehrad Avatar asked May 29 '14 00:05

Mehrad


People also ask

Which is the correct for () statement to run an infinite loop in C#?

Or in other words, an infinite loop is a loop in which the test condition does not evaluate to false and the loop continues forever until an external force is used to end it. You can create an infinite loop: Using for loop.

How do you know if its an infinite loop?

In each iteration you calculate a number (the sum of the squares of the digits or the previous number). You can put all those numbers in a Set. If in some iteration you calculate a number that is already in that Set, you know that you are stuck in an infinite loop.

Why is my while loop infinite?

Basically, the infinite loop happens when the condition in the while loop always evaluates to true. This can happen when the variables within the loop aren't updated correctly, or aren't updated at all.


3 Answers

You should use CancellationTokenSource. But don't pass the Token to the Task.Run method and don't throw an exception. Simply check if cancellation was requested and then stop.

CancellationTokenSource cts = new CancellationTokenSource();
CancellationToken ct = cts.Token;

Task.Run(
    async () =>
    {
        while (!ct.IsCancellationRequested)
        {              
            await ConnectAsync();
            await ReadAsync();
            await WriteAsync();
            await DisconnectAsync();
        }
    });

cts.Cancel();

When you pass a CancellationToken to the Task itself(Task.Run(async () => ..., ct)), you can't use it inside the delegate. It will only cancel the task if cancellation was called before the task started running. After it has begun, calling Cancel won't have any effect.

like image 153
i3arnon Avatar answered Oct 23 '22 04:10

i3arnon


Create a CancellationTokenSource and pass its Token to the async task. This will allow you to signal to your async tasks that cancellation is requested. More info: http://msdn.microsoft.com/en-us/library/hh873177(v=vs.110).aspx

like image 22
SKall Avatar answered Oct 23 '22 02:10

SKall


I would strongly recommend everybody to have a read about three different methods of Asynchronous Programming Patterns and the use of the recent and preferred method Task-based Asynchronous Pattern (TAP)

Asynchronous Programming Model (APM)
Describes the legacy model that uses the IAsyncResult interface to provide asynchronous behavior. This model is no longer recommended for new development.

Event-based Asynchronous Pattern (EAP)
Describes the event-based legacy model for providing asynchronous behavior. This model is no longer recommended for new development.

Task-based Asynchronous Pattern (TAP)
Describes the new asynchronous pattern based on the System.Threading.Tasks namespace. This model is the recommended approach to asynchronous programming in the .NET Framework 4 and later versions.

Thanks to @SKall for pointing me to the right direction.

like image 3
Mehrad Avatar answered Oct 23 '22 02:10

Mehrad