Calling a blocking function

I would like a blocking sync function to be called when a button is pressed. Once the function returns, its return value should be displayed.

Based on the documentation, I think I’ll have to return a Command from the update() method of my Application. I think I should create the command with Command::single(), Command::perform(), or Command::run().

But these functions aren’t well-documented, so I wasn’t able to figure out how to use them to achieve what I’m trying to do.

Any pointers are much appreciated!

This might help you Blocking Code - Unofficial Iced Guide

Note that this Guide is partially written for a development version of iced that has not been released yet.
You might want to read all chapters on Commands/Tasks.

Thank you, that answered my question!

I was initially confused why the second argument of Command::perform() is FnOnce. But now I see it’s an enum-variant constructor! I find that a bit un-intuitive.

Another thing I’m a bit confused about is what the Action in the Command::single(action: Action<T>) is. I couldn’t find more documentation about it.

I think it is something from iced_runtime. It wont be there in the next release.

1 Like

I think you are overthinking the problem here.

The normal pattern is to call your function directly in the update() method and store the result in some state variable of your application. You can then just return Command::none() (or Task::none() in the development branch). Your view() method will be called and you can display whatever you need to.

Ah, so is it fine to block in the update() method?

@shartrec
If you have a blocking function in your update. Your app will freeze/block until the blocking function has finished!

Therefore you should not call a blocking function that takes a while in your update function!

@JL710 Agreed. I think I misunderstood @manforowicz original question. If you have a function that will run for an extended period of time (more than a few milliseconds at most) then you should use the Task api.

So as a simplest example

// In update return a task
Message::ButtonPressed => {
    Task::perform(async  {
            // Some long running task that returns something (here a f64)
            2.0
        }, 
        // Map the result to some Message that will be sent in the event loop
        |a|-> Message {
            Message::Evaluate(a)
        }
    )
}

@JL710 , This is what I do, can you confirm this is in fact correct.

1 Like

The code that you have shown looks good to me.

@shartrec you can simplify that even further by replacing

|a|-> Message {
    Message::Evaluate(a)
}

with

Message::Evaluate