I came to the following solution for my long running tasks, using 
go-routines & the context package,

https://play.golang.org/p/2V_29lHt4Wn

package main

import (
   "context"
   "fmt"
   "time"
)

//LongRunningTask
func LongRunningTask(ctx context.Context, index int) (err error) {
   // we'll signal on that channel when we finished
   var finished chan struct{}
   fmt.Printf("Starting task %d at: %s\n", index, time.Now())
   var cancelWork =  make(chan struct{},0)
   go func() {
      workloop:
      for i:= 0 ;i < 10 ;i++{
         // sleeping for a  long time
         time.Sleep(time.Second * 2)
         select {
         case <-cancelWork:
            fmt.Printf("Canceling work for Index: %d\n",index)
            break workloop
         default:
         }
      }
      finished <- struct{}{}
   }()

   select {
   // when the task finished normal we'll get a notification on the finished 
channel
   case <-finished:
      fmt.Printf("Task %d  finished at:%s\n", index, time.Now())
      return nil

   // If the context gets canceled we receive a signal on that channel
   case <-ctx.Done():
      err := ctx.Err()
      _=err
      //the context.Err() method gives us the reason why it was canceled
      fmt.Printf("task %d aborted reason:%s at: %s\n", index, ctx.Err(), 
time.Now())
      cancelWork <- struct{}{}
      return ctx.Err()
   }

}

func main() {
   var ctx context.Context

   // get a new Context and  the corresponding cancel function
   ctx, cancel := context.WithCancel(context.Background())

   // create a new context with a timeout value of 4 Seconds derived from the 
context above
   ctx, _ = context.WithTimeout(ctx, time.Second*4)

   // Sleeping for one Second to clarify that the timeout is running from the 
point where it is created
   time.Sleep(time.Second * 1)

   fmt.Printf("Starting background tasks time %s", time.Now())
   for i := 0; i < 7; i++ {
      go LongRunningTask(ctx, i)

   }

   // if we sllep longer than the timeout we'll see that the tasks will be 
canceled after timeout
   time.Sleep(time.Second * 8)

   // The call of the cancel function has only effect when we slept shorter 
then the defined timeout
   // if so the single call of the cancel function will send a cancellation 
information to all child context
   cancel()

   // Sleep a while to see the cancellation messages
   time.Sleep(time.Second * 4)

}


Am Freitag, 16. März 2018 15:45:00 UTC+1 schrieb Sathish VJ:
>
> All the examples I've seen use some kind of ticker to run various cases of 
> a select statement.  But how does one run a long running task that is still 
> cancelable?  
>
>
> In the example below the quit part is never reached.  
>
> https://play.golang.org/p/PLGwrUvKaqn  (it does not run properly on 
> play.golang.org).
>
> package main
>
>
> import (
>  "fmt"
>  "os"
>  "time"
> )
>
>
> func f(quit chan bool) {
>  for {
>    select {
>    case <-time.After(0 * time.Second):
>      // start long running task immediately.
>      for {
>        time.Sleep(500 * time.Millisecond)
>        fmt.Printf(". ")
>      }
>    case <-quit:
>      fmt.Println("quit called")
>      //deallocate resources in other long running task and then return 
> from function.
>      os.Exit(0) // or return
>    }
>  }
> }
>
>
> func main() {
>  var quit chan bool
>  go f(quit)
>
>
>  println("quit sending ... ")
>  quit <- true
>  println("after quit sent")
>
>
>  var i chan int
>  <-i
> }
>
>
>

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to