Only a detail, but why not this instead as the API? func LongRunningTask(cancel <-chan struct{}, index int) (err error) {
Matt On Monday, March 19, 2018 at 7:43:19 AM UTC-5, rog wrote: > > Why not something more like this? https://play.golang.org/p/3t4UtoFkoIt > > A lot of this comes down to what that long running task is doing. > If it's hard at work doing computational work, the polling approach > might be appropriate. > If it's mostly waiting on external events then passing the context > instance down and selecting > on the Done channel is probably the way forward. > > On 19 March 2018 at 07:44, Sathish VJ <sath...@gmail.com <javascript:>> > wrote: > > Looks like this last one works but also quite complicated. > > > > One question ... what is the effect of having "default" on line 24 as > empty? > > > > > > On 18 March 2018 at 14:21, 'Reinhard Luediger' via golang-nuts > > <golan...@googlegroups.com <javascript:>> wrote: > >> > >> 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 a topic in the > >> Google Groups "golang-nuts" group. > >> To unsubscribe from this topic, visit > >> https://groups.google.com/d/topic/golang-nuts/l2A0PS91T0A/unsubscribe. > >> To unsubscribe from this group and all its topics, send an email to > >> golang-nuts...@googlegroups.com <javascript:>. > >> For more options, visit https://groups.google.com/d/optout. > > > > > > -- > > 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...@googlegroups.com <javascript:>. > > For more options, visit https://groups.google.com/d/optout. > -- 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.