【问题标题】:Can I run interval timers in AwesomeWM?我可以在 AwesomeWM 中运行间隔计时器吗?
【发布时间】:2020-04-26 03:23:32
【问题描述】:

我在 Manjaro Linux (Arch) 上使用 Awesome 4.3 我从 KDE 桌面更改为 XFCE 桌面。我写了一个壁纸切换器,它会在四个独立的屏幕上随机改变壁纸。出于开发目的,我在标准 Lua 文件中编写了随机化例程。我将它添加到 rc.lua,但 Lua 计时器(luv)似乎没有在 rc.lua 中运行。我分别检查了所有方法以从我的随机例程中加载壁纸,当我直接为四个屏幕调用一组文件时,它们完美地工作。一旦我添加了间隔计时器,什么都没有发生,没有错误,什么都没有。

这是简化为仅加载一个屏幕的代码,我是否遗漏了什么,取出了令人敬畏的对象并替换为打印语句,它在标准 Lua 文件中完美运行

感谢任何帮助

local lfs = require('lfs') -- lua file system
local uv = require('luv') -- lua timer
local dir = "/home/jerry/Documents/wallpaper"
local images = {} -- images collection
local idx = 0
math.randomseed(os.time())

local function tablelength(T)
    local count = 0
    for _ in pairs(T) do count = count + 1 end
    return count
end

local function readImages(path)
    for file in lfs.dir(path) do
        if file ~= "." and file ~= ".." then
            images[idx] = path .. '/' .. file
            idx = idx + 1
        end
    end
end

readImages(dir);
imageCount = tablelength(images)

local function getImage()
    number = math.random(1, imageCount)
    return images[number]
end

local function setInterval(interval, callback)
    local timer = uv.new_timer()
    uv.timer_start(timer, 0, interval, callback)
    return timer
end

local function cb()
    local path = getImage()
    gears.wallpaper.maximized(path, screen[1], true)
end


timer1 = setInterval(1000, cb)
 local function cb(gears, getImage, screen, screenIndex)
    return function()
        print(gears)
        print(getImage())
        print(screen)
        print("Screen " .. screenIndex)
        return gears.wallpaper.maximized(getImage(), screen[screenIndex], true)
    end
end 

【问题讨论】:

    标签: lua awesome-wm


    【解决方案1】:

    你忘了打电话给uv.run()。该调用运行计时器。 但是,它也不会运行其他任何东西,因此 AwesomeWM 将停止工作。

    uv.run() 运行一个主循环。此循环等待事件(例如:计时器到期),然后处理该事件。 AwesomeWM 也使用主循环。它运行 GLib 的 GMainLoop

    由于您不能同时运行两个主循环,因此您必须使用 GLib 和 AwesomeWMs 工具。 我找到了一些 luv 的文档 timer_start: https://github.com/luvit/luv/blob/master/docs.md#uvtimer_starttimer-timeout-repeat-callback 据此,您的timer_start(timer, 0, interval, callback) 意味着计时器立即触发,然后每秒触发一次。 AwesomeWM 版本是:

    local gears = require("gears") -- This is part of AwesomeWM
    local timer1 = gears.start_new(1, function()
        print("I run once per second")
        return true -- Signal that the timer should continue running
    end)
    timer1:emit_signal("timeout") -- Cause the callback function to run right now
    

    gears.timer 使用 GLib 运行计时器:https://github.com/awesomeWM/awesome/blob/87e7b84ff54c050f86541421ec0aa93e325dd49d/lib/gears/timer.lua#L94

    【讨论】:

    • 嗨,谢谢,是的,我不小心把 uv.run() 从代码中遗漏了,是的,当我使用它时它会被锁定。这就是我伸出援手的原因。我将看看 gears 选项,我遇到的另一个问题是因为它是异步的,所以我丢失了本地状态,并且必须确保在执行之前将所有状态传递给方法。感谢您对齿轮的提醒,我会尝试一下并让您知道
    • 你说的“失去所有地方州”到底是什么意思? Lua 闭包应该仍然像以前一样继续。例如,local i = 1; gears.timer.start_new(1, function() print(i) ; i = i + 1 ; return true ; end) 应该向上计数。
    • 我在回调中指的是,我应该更准确。计时器是一个异步过程,并且在回调中丢失了所有关闭状态,我通过在它需要的状态中进行柯里化来解决这个问题。
    • 但是我上一条评论中的示例也是异步的,它不会丢失状态(它在调用之间保持i 的值),因此它不会丢失所有关闭状态。这正是 Lua 中的闭包。我很困惑...
    • 好的,我首先走的是阻力最小的路径,只是在计时器 CB 中添加了对垃圾收集器的调用,而没有在链接示例中调用“启动和停止”,它似乎可以解决问题.我在 awmtt 中运行了一个小时,一切都很好,我使用短时间来加速出现问题的可能性,这很好。然后我将它加载到我的正常 rc.lua 中并设置更合理的计时器。它已经运行了一段时间,没有发生任何事故。再次感谢您的帮助和非凡的耐心。 :)
    【解决方案2】:

    这是使用@uli schlachter 的建议完成的实现,但是我发现它似乎会定期消耗大量的内存和 CPU。如果有人知道它会很棒的原因,这比 bash 或其他实现要容易得多。

    -- wallpaper changer routine
    local lfs = require('lfs') -- lua file system
    local dir = "/home/jerry/Documents/wallpaper" --images location
    local images = {} -- images collection
    local idx = 0 -- index for the image collection
    math.randomseed(os.time())
    -- function to generate the image count for the randomize function
    local function tablelength(T)
        local count = 0
        for _ in pairs(T) do count = count + 1 end
        return count
    end
    -- function to read the images from the directory 
    local function readImages(path)
        for file in lfs.dir(path) do
            if file ~= "." and file ~= ".." then
                images[idx] = path .. '/' .. file
                idx = idx + 1
            end
        end
    end
    -- execute read the images
    readImages(dir);
    -- grab the image count
    imageCount = tablelength(images)
    -- Generate the random image path
    local function getImage()
        number = math.random(1, imageCount)
        return images[number]
    end
    -- call back for timer 
    local function cb(screenIndex)
        return function()
            print(getImage())
            gears.wallpaper.maximized(getImage(), screen[screenIndex], true)
            return true;
        end
    end
    -- partial application of the
    -- call back for the timer
    -- pre-apply the screen index to create the
    -- four separate cb's one for each screen
    cb1 = cb(1)
    cb2 = cb(2)
    cb3 = cb(3)
    cb4 = cb(4)
    -- create the timers with unique time spans 
    -- to sell the ramdomized approach 
    local timer1 = gears.timer.start_new(14, cb1)
    local timer2 = gears.timer.start_new(16, cb2)
    local timer3 = gears.timer.start_new(18, cb3)
    local timer4 = gears.timer.start_new(20, cb4)
    -- trigger the timers 
    timer1:emit_signal("timeout")
    timer2:emit_signal("timeout")
    timer3:emit_signal("timeout")
    timer4:emit_signal("timeout")
    

    调用垃圾收集器的回调的最终版本

    -- call back for timer
    local function cb(screenIndex)
        return function()
            gears.wallpaper.maximized(getImage(), screen[screenIndex], true)
            collectgarbage("step", 4000)
            return true;
        end
    end
    

    【讨论】:

    • 如果您想要随机超时,那么您可以这样做。 return false 在您的回调中停止计时器并启动一个新计时器。
    猜你喜欢
    • 2023-03-21
    • 1970-01-01
    • 1970-01-01
    • 2011-03-15
    • 2021-02-16
    • 2015-06-19
    • 2021-09-04
    • 2019-01-07
    • 1970-01-01
    相关资源
    最近更新 更多