首页 > 解决方案 > 如何在非同步回调中​​使用异步移动闭包?

问题描述

这是一个 fltk 按钮的点击回调函数,我想在点击一个按钮时执行一个数据库查询。

    //button click even
    ui.but.set_callback(async move |_| {
        let txt = "Some long text!Some long text!Some long text!Some long text!Some long text!\n";
        log.buffer().unwrap().append(txt);
        my_db::sqlserver_mod2::sql2().await.unwrap();
    });

我收到一个错误:

[E0308] mismatched types. 
[Note] expected `()`, found opaque type

如何在非同步回调中​​使用异步移动闭包?

标签: asynchronousrust

解决方案


的签名set_callback()是:

fn set_callback<F: FnMut(&mut Self) + 'static>(&mut self, cb: F) 

换句话说,回调不能返回任何东西。但是你的回调

async move |_| {
  //skipped      
});

返回类型为:

impl Future<Output=()>

这是一个不返回任何内容的匿名未来。所以你不能使用异步闭包作为你的回调。

相反,您应该传递预期类型的​​闭包并在其中进行处理:

ui.but.set_callback(move |_| {
        let txt = "Some long text!Some long text!Some long text!Some long text!Some long text!\n";
        log.buffer().unwrap().append(txt);

         //acquire a runtime somehow, see the docs of your preferred runtime
        runtime.spawn(async {
            my_db::sqlserver_mod2::sql2().await.unwrap();
        });

    });

最后,但并非最不重要的一点 - 您应该避免在 UI 中进行缓慢的操作,因为它会显得无响应。考虑将工作卸载到另一个线程。例如,您可以启动 tokio 并预生成应在生产者-消费者模型中工作的处理程序,并且只需通过来自 UI(生产者)的通道传递命令。


推荐阅读