As an MWE I have a simple Dash.jl app that incremets a progress bar once you hit start and stops it when hitting a stop button.
What I’d like it to do is to start running a task when hitting start and then make some progress animation and stop it once the Task is finished.
However I don’t know how I can refer to the created Task in sequent invokations of the callback, since for storing it I’d have to serialize it somehow, which might be possible, but I don’t know how.
But I thought it would be possible to serialize just the address, that is printed when printing the Task, but I also don’t find a way to access it nor how to retrieve a Task if I had the address.
Is there any way to achieve any of this or is there an alternative way of doing this?
using Dash
using Base.Threads
app = dash()
app.layout = html_div() do
children = [
dcc_interval(id = "interval-component", interval = 1000, n_intervals = 0, disabled = true),
html_progress(id = "progress-bar", value = "0", max = 100),
html_div(id = "progress-description"),
html_button("Start", id = "start-button", n_clicks = 0),
html_button("Stop", id = "stop-button", n_clicks = 0),
dcc_store(id = "store", data = Dict(:running => false, :complete => false)), # Initial state
]
end
# Single callback to handle both Start and Stop buttons
callback!(
app,
Output("interval-component", "disabled"),
Output("store", "data"),
Input("start-button", "n_clicks"),
Input("stop-button", "n_clicks"),
Input("progress-bar", "value"),
State("store", "data"),
) do start_clicks, stop_clicks, val, stored_data
stored_data = Dict(pairs(stored_data))
if val == "100" && !stored_data[:complete]
stored_data[:running] = false
stored_data[:complete] = true
return true, stored_data
end
ctx = callback_context()
button_id = ""
!isempty(ctx.triggered) && (button_id = split(ctx.triggered[1].prop_id, ".")[1])
should_stop = if button_id == "start-button"
t = Threads.@spawn sleep(10) # i wan't to refer to this task at a later invocation of this callback
@show t
stored_data[:complete] = false
stored_data[:running] = true
false # Enable interval
elseif button_id == "stop-button"
stored_data[:running] = false
true # Disable interval
else
stored_data[:running] ? false : true # No change
end
return should_stop, stored_data
end
# Callback to update progress bar and description
callback!(
app,
Output("progress-bar", "value"),
Output("progress-description", "children"),
Output("interval-component", "n_intervals"),
Input("interval-component", "n_intervals"),
State("store", "data"),
) do n_intervals, stored_data
progress_percentage = min(n_intervals * 10, 100)
description = "$progress_percentage % Complete"
if progress_percentage >= 100
return string(progress_percentage), description, 0 # Reset intervals after completion
end
return string(progress_percentage), description, n_intervals
end
run_server(app, debug = true)