Giving user feedback during long-running process and user-interface/buissiness-logic separation
When a long-running process is being executed, it is a good practice to provide feedback to the user, for example, updating a progress bar.

Some FAQs for GUI libraries suggest something like this:

    function long_running_progress()
        do_some_work()
        update_progress_bar()
        while finish
            do_some_work()
            update_progress_bar()
        end while
    end function

Anyway, we know it is a best practice to separate business logic code from user interface code. The example above is mixing user interface code inside a business logic function.

What is a good technique to implement functions in the business logic layer whose progress could be easily tracked by an user interface without mixing layers?

Answers for any language or platform are welcome.
Giving user feedback during long-running process and user-interface/buissiness-logic separation
===

When a long-running process is being executed, it is a good practice to provide feedback to the user, for example, updating a progress bar.

Some FAQs for GUI libraries suggest something like this:

    function long_running_progress()
        do_some_work()
        update_progress_bar()
        while finish
            do_some_work()
            update_progress_bar()
        end while
    end function

Anyway, we know it is a best practice to separate business logic code from user interface code. The example above is mixing user interface code inside a business logic function.

What is a good technique to implement functions in the business logic layer whose progress could be easily tracked by an user interface without mixing layers?

Answers for any language or platform are welcome.