I did a progress dialog for our WebApp. It worked fine, but was a bit overkill and in the end we went back to just a "spinning wheel" and moved the long running processes to a scheduled task instead.

I created a progress table containing an ID, a progress percent, a text and a status.
The client first allocated a progress-ID, and then passed that to the task. It then polled the record via a timer, showing the progress in a dialog.
The server updated the percentage and the text.
I used the status to indicate when the task was finished, so the client could close the progress dialog.
I also had a "Cancel" button in the dialog, which set the status in the records. The server checked this and could cancel the task.