для выбора группы вопросов - PullRequest
0 голосов
/ 14 апреля 2020

Я пытаюсь написать функцию для выполнения нескольких заданий, когда все задания выполнены, я хочу, чтобы элемент управления go после wg.Wait (). Я упомянул различные проблемы, с которыми я сталкиваюсь в комментариях в коде.

Как я могу заставить его работать?

func (q *ChanExecutor) Perform(ctx context.Context, name string, taskData *interface{}) chan *job.JobResult {
    var waitgroup sync.WaitGroup
    waitgroup.Add(1)
    go func(wg *sync.WaitGroup) {
        for j := range q.jobCh { // This is the channel which gives jobs
            wg.Add(1)
            go func(qq *ChanExecutor, jVal job.Job) { // we are just passing these values to closure. Is this necessary?
                jobResultChannel:= jVal.Do(ctx) // Here we are executing the job as result which sends another channel of results
                donech := jVal.DoneCh() // Job returns another channel which tells if that job is done
                for true {
                    select {
                    case res := <-jobResultChannel:
                        q.result <- res // From the result we are passing that result to another channel
                    case syncJobDone := <-donech:
                        if syncJobDone {
                            donech = nil // here if the donech receives true it should come out of the select and for loop and the goroutine. How to do that?
                            // Another thing here, if the donech returns true before jobResultChannel then it should still go to jobResultChannel's case block
                            // The jVal.Do(ctx) executes the job and returns channel but in my case before starting the forloop both channels has values and donech has true value
                            wg.Done()
                            break
                        }
                    }
                }
            }(q, *j)
        }
    }(&waitgroup)
    go func(wg *sync.WaitGroup, qq *ChanExecutor) {
        time.Sleep(200 * time.Millisecond) // Here is another blunder. If I don't sleep here, randomly, it goes after wg.Wait()
        // even though all the jobs are not done.
        wg.Done() // REmoving the one which was added immediately after creating wg instance.
        wg.Wait()
        fmt.Println("Wait finish")
        qq.Done()
    }(&waitgroup, q)
    fmt.Printf("returning result channel not result")
    return q.result
}

1 Ответ

0 голосов
/ 15 апреля 2020

Во-первых, вы должны удалить сон и wg.Done из второй программы. Иногда происходит сбой без сна, потому что иногда первая программа не имеет возможности добавить к wg до того, как вторая удалит его.

Во-вторых, вы пытаетесь завершить выполнение программы, поэтому только это:

if syncJobDone {
   wg.Done()
   return
}
...