After testing for a night, I find out the solution.
def task_function(arg):
cancel_flag == False
main loop:
if cancel_flag:
break
...
...
...
def set_cancel_flag():
nonlocal cancel_flag
cancel_flag = True
mw.taskman.run_on_main(lambda: set_cancel_flag() if mw.progress.want_cancel() else None)
Edited: Thanks to @dae, I refined the code:
def task(arg):
mw.taskman.run_in_background(lambda: task_function(arg))
def task_function(arg):
...
...
...
main loop:
...
...
...
if mw.progress.want_cancel()
break