【发布时间】:2021-03-31 19:55:29
【问题描述】:
我正在为 golang 学习 fyne.io,我遇到了一个问题。我做了一个最小的仪表板交互任务,应该同时开始,问题是用户必须有权随时停止任何任务。我决定使用通道来发送任务和上下文来停止任务,但这不起作用,我的意思是当任务到达通道时,worker(task *Task) 开始,我点击停止,当这种情况发生时,startTask(task *Task) 停止工作,但@987654324 @不停。怎么了?我做错了吗?
package main
import (
"context"
"fmt"
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/app"
"fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/theme"
"fyne.io/fyne/v2/widget"
"github.com/k0kubun/pp"
"time"
)
type Task struct {
ID int
Chancel context.CancelFunc
}
var channelTask chan *Task
func worker(task *Task) {
for i := 0; i < 10; i ++ {
fmt.Println(fmt.Sprintf("Task ID: %d running...%d", task.ID, i))
time.Sleep(1 * time.Second)
}
}
func startTask(task *Task) {
go func() {
ctx, cancel := context.WithCancel(context.Background())
for {
select {
case <- ctx.Done():
pp.Println(fmt.Sprintf("Task ID: %d stopped!", task.ID))
return
case task := <-channelTask:
task.Chancel = cancel
fmt.Println(fmt.Sprintf("Task ID: %d stared!", task.ID))
go func() {
worker(task)
}()
default:
continue
}
}
}()
}
func main() {
a := app.New()
w := a.NewWindow("Testing")
channelTask = make(chan *Task)
w.SetContent(createList())
w.CenterOnScreen()
w.Resize(fyne.Size{
Width: 500,
Height: 300,
})
w.SetFixedSize(true)
w.ShowAndRun()
}
func createList() *widget.List {
tasks := createTasks()
return widget.NewList(
func() int {
return len(tasks)
},
func() fyne.CanvasObject {
return container.NewGridWithColumns(3,
widget.NewLabel(""),
widget.NewButtonWithIcon("Run", theme.MediaPlayIcon(), func() {}),
widget.NewButtonWithIcon("Stop", theme.MediaStopIcon(), func() {}),
)
},
func(id widget.ListItemID, item fyne.CanvasObject) {
task := tasks[id]
item.(*fyne.Container).Objects[0].(*widget.Label).SetText(fmt.Sprintf("Task ID: %d", task.ID))
buttonRun := item.(*fyne.Container).Objects[1].(*widget.Button)
buttonStop := item.(*fyne.Container).Objects[2].(*widget.Button)
buttonStop.Disable()
buttonRun.OnTapped = func() {
fmt.Println(fmt.Sprintf("Task ID: %d Start button pushed.", task.ID))
startTask(task)
buttonRun.Disable()
buttonStop.Enable()
channelTask <- task
return
}
buttonStop.OnTapped = func() {
fmt.Println(fmt.Sprintf("Task ID: %d Stop button pushed.", task.ID))
task.Chancel()
buttonRun.Enable()
return
}},
)
}
func createTasks() []*Task {
var tasks []*Task
for i := 0; i < 5; i ++ {
tasks = append(tasks, &Task{ID: i})
}
return tasks
}
【问题讨论】:
标签: go concurrency