草庐IT

关闭 channel `shutdown msg` 后执行例程不打印 `done`

coder 2024-07-05 原文

从同一 channel 读取的两个 go 例程。在 done channel 关闭后,第一个 go 例程从不打印其关闭消息,而第二个 go 例程始终打印。

为什么第一个 go 例程的消息没有打印出来,方法甚至返回

主.go

func main() {
done := make(chan bool)
c := make(chan os.Signal, 1)

cameras := client.CameraConfig()
client.DrawUserControls(cameras)

operator := client.NewOperator(cameras)
go operator.UserInputListener(done)
go operator.ParseAndExecuteUserCommand(done)

signal.Notify(c, os.Interrupt)
for range c {
    close(done)
    break
}

log.Println("Interrupt signal received. Shutting client down....")
time.Sleep(5 * time.Second)
}

客户端.go

func (o *Operator) UserInputListener(done <-chan bool) {
    reader := bufio.NewReader(os.Stdin)
    for {
        select {
        case <-done:
            log.Println("Keyboard listener shutting down.") // <-- this never prints
            return
        default:
            line, _, err := reader.ReadLine()
            if err != nil {
                log.Println(err)
            }

            data := strings.Split(string(line), "")

            id, err := strconv.Atoi(data[1])
            if err != nil {
                log.Println(err)
                continue
            }

            switch data[0] {
            case "b":
                o.Controls <- Ctrl{
                    Identifier: id,
                    Ctrl:       "run",
                }
            case "t":
                o.Controls <- Ctrl{
                    Identifier: id,
                    Ctrl:       "terminate",
                }
            case "r":
                o.Controls <- Ctrl{
                    Identifier: id,
                    Ctrl:       "record",
                }
            case "s":
                o.Controls <- Ctrl{
                    Identifier: id,
                    Ctrl:       "stop",
                }
            }
        }
    }
}

func (o *Operator) ParseAndExecuteUserCommand(done <-chan bool) {
    for {
        select {
        case <-done:
            log.Println("Command operator shutting down.")
            return
        case ctrl := <-o.Controls:
            switch ctrl.Ctrl {
            case "run":
                o.Room[ctrl.Identifier].Run()
            case "terminate":
                o.Room[ctrl.Identifier].Close()
            case "record":
                o.Room[ctrl.Identifier].Write()
            case "stop":
                o.Room[ctrl.Identifier].Stop()
            }
        }
    }
}

最佳答案

原因是因为你创建了同步 channel ,你推送了1条消息,然后你也只能读取一次。那是因为您只能从 done channel 中读取 1 个(随机)。

关闭 goroutine 的方法是使用 WaitGroup:
主要Go:

var (
    done            chan bool
)

func main() {
    cameras := client.CameraConfig()
    client.DrawUserControls(cameras)
    operator := client.NewOperator(cameras)

    done = make(chan bool, 1)
    wg := &sync.WaitGroup{}
    wg.Add(2)
    go operator.UserInputListener(done, wg)
    go operator.ParseAndExecuteUserCommand(done, wg)

    handleShutdown()
    wg.Wait()
}


func handleShutdown() {
    ch := make(chan os.Signal, 1)
    go func() {
        <-ch //wait for application terminating
        log.Println("Shutdown received.")
        close(done)
    }()
    signal.Notify(ch, os.Interrupt, syscall.SIGTERM, syscall.SIGHUP)
}

客户端.go:

func (o *Operator) UserInputListener(done <-chan bool, wg *sync.WaitGroup) {
    defer wg.Done()
    for {
        select {
        case <-done:
            log.Println("Keyboard listener shutting down.") 
            return
        ........
        }
    }
}

func (o *Operator) ParseAndExecuteUserCommand(done <-chan bool, wg *sync.WaitGroup) {
    defer wg.Done()
    for {
        select {
        case <-done:
            log.Println("Command operator shutting down.") 
            return
        ........
        }
    }
}

使用这个 link详情

关于关闭 channel `shutdown msg` 后执行例程不打印 `done`,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45571628/

有关关闭 channel `shutdown msg` 后执行例程不打印 `done`的更多相关文章

  1. ruby-openid:执行发现时未设置@socket - 2

    我在使用omniauth/openid时遇到了一些麻烦。在尝试进行身份验证时,我在日志中发现了这一点:OpenID::FetchingError:Errorfetchinghttps://www.google.com/accounts/o8/.well-known/host-meta?hd=profiles.google.com%2Fmy_username:undefinedmethod`io'fornil:NilClass重要的是undefinedmethodio'fornil:NilClass来自openid/fetchers.rb,在下面的代码片段中:moduleNetclass

  2. ruby - Chef 执行非顺序配方 - 2

    我遵循了教程http://gettingstartedwithchef.com/,第1章。我的运行list是"run_list":["recipe[apt]","recipe[phpap]"]我的phpapRecipe默认Recipeinclude_recipe"apache2"include_recipe"build-essential"include_recipe"openssl"include_recipe"mysql::client"include_recipe"mysql::server"include_recipe"php"include_recipe"php::modul

  3. ruby - 为什么 Ruby 的 each 迭代器先执行? - 2

    我在用Ruby执行简单任务时遇到了一件奇怪的事情。我只想用每个方法迭代字母表,但迭代在执行中先进行:alfawit=("a".."z")puts"That'sanalphabet:\n\n#{alfawit.each{|litera|putslitera}}"这段代码的结果是:(缩写)abc⋮xyzThat'sanalphabet:a..z知道为什么它会这样工作或者我做错了什么吗?提前致谢。 最佳答案 因为您的each调用被插入到在固定字符串之前执行的字符串文字中。此外,each返回一个Enumerable,实际上您甚至打印它。试试

  4. ruby - 如何关闭 ruby​​ gem "Spreadsheet?"中的文件 - 2

    下面的代码在我第一次运行它时就可以正常工作:require'rubygems'require'spreadsheet'book=Spreadsheet.open'/Users/me/myruby/Mywks.xls'sheet=book.worksheet0row=sheet.row(1)putsrow[1]book.write'/Users/me/myruby/Mywks.xls'当我再次运行它时,我会收到更多消息,例如:/Library/Ruby/Gems/1.8/gems/spreadsheet-0.6.5.9/lib/spreadsheet/excel/reader.rb:11

  5. ruby - 检查是否通过 require 执行或导入了 Ruby 程序 - 2

    如何检查Ruby文件是否是通过“require”或“load”导入的,而不是简单地从命令行执行的?例如:foo.rb的内容:puts"Hello"bar.rb的内容require'foo'输出:$./foo.rbHello$./bar.rbHello基本上,我想调用bar.rb以不执行puts调用。 最佳答案 将foo.rb改为:if__FILE__==$0puts"Hello"end检查__FILE__-当前ruby​​文件的名称-与$0-正在运行的脚本的名称。 关于ruby-检查是否

  6. postman——集合——执行集合——测试脚本——pm对象简单示例02 - 2

    //1.验证返回状态码是否是200pm.test("Statuscodeis200",function(){pm.response.to.have.status(200);});//2.验证返回body内是否含有某个值pm.test("Bodymatchesstring",function(){pm.expect(pm.response.text()).to.include("string_you_want_to_search");});//3.验证某个返回值是否是100pm.test("Yourtestname",function(){varjsonData=pm.response.json

  7. ruby-on-rails - rbenv:从 RVM 移动到 rbenv 后,在 Jenkins 执行 shell 中找不到命令 - 2

    我从Ubuntu服务器上的RVM转移到rbenv。当我使用RVM时,使用bundle没有问题。转移到rbenv后,我在Jenkins的执行shell中收到“找不到命令”错误。我内爆并删除了RVM,并从~/.bashrc'中删除了所有与RVM相关的行。使用后我仍然收到此错误:rvmimploderm~/.rvm-rfrm~/.rvmrcgeminstallbundlerecho'exportPATH="$HOME/.rbenv/bin:$PATH"'>>~/.bashrcecho'eval"$(rbenvinit-)"'>>~/.bashrc.~/.bashrcrbenvversions

  8. ruby - 如何使用 Selenium Webdriver 根据 div 的内容执行操作? - 2

    我有一个使用SeleniumWebdriver和Nokogiri的Ruby应用程序。我想选择一个类,然后对于那个类对应的每个div,我想根据div的内容执行一个Action。例如,我正在解析以下页面:https://www.google.com/webhp?sourceid=chrome-instant&ion=1&espv=2&ie=UTF-8#q=puppies这是一个搜索结果页面,我正在寻找描述中包含“Adoption”一词的第一个结果。因此机器人应该寻找带有className:"result"的div,对于每个检查它的.descriptiondiv是否包含单词“adoption

  9. ruby-on-rails - Rake 任务仅调用一次时执行两次 - 2

    我写了一个非常简单的rake任务来尝试找到这个问题的根源。namespace:foodotaskbar::environmentdoputs'RUNNING'endend当在控制台中执行rakefoo:bar时,输出为:RUNNINGRUNNING当我执行任何rake任务时会发生这种情况。有没有人遇到过这样的事情?编辑上面的rake任务就是写在那个.rake文件中的所有内容。这是当前正在使用的Rakefile。requireFile.expand_path('../config/application',__FILE__)OurApp::Application.load_tasks这里

  10. ruby-on-rails - Ruby 的 'open_uri' 是否在读取或失败后可靠地关闭套接字? - 2

    一段时间以来,我一直在使用open_uri下拉ftp路径作为数据源,但突然发现我几乎连续不断地收到“530抱歉,允许的最大客户端数(95)已经连接。”我不确定我的代码是否有问题,或者是否是其他人在访问服务器,不幸的是,我无法真正确定谁有问题。本质上,我正在读取FTPURI:defself.read_uri(uri)beginuri=open(uri).readuri=="Error"?nil:urirescueOpenURI::HTTPErrornilendend我猜我需要在这里添加一些额外的错误处理代码...我想确保我采取一切预防措施来关闭所有连接,这样我的连接就不是问题所在,但是我

随机推荐