If you don’t want to block user input during your tool’s operation, a modeless window that triggers external events is the only way to go. If you just try to use a modeless window that makes regular API calls, it will almost always crash Revit. You need to trigger your API calls within an external event.
I did so in this earlier forum post where I used a XAML UI to trigger external events. (you don’t have to read through the whole thread, just find where I posted the finished code near the bottom and study up on the code related to external events.) Ehsan has also posted a good video tutorial on the pyRevit youtube channel. It’s a lot to learn, but it works very well in the end.
https://discourse.pyrevitlabs.io/t/xaml-ui-unresponsive-until-focus-is-switched-to-other-window/3162/8