Finish decoupling UI from code conversion #11
Merged
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
DoEvents is typically considered harmful. You can see some fun things on this topic if you google it. It causes the message pump to handle messages from more than one point in the program. This can cause events to execute out of order and event handlers to reenter themselves. I've seen it produce bugs in my own code and in third-party UI libraries that were not expecting to be subjected to such cruel and unusual interrogation.
The DoEvents docs page has this warning in a large red paragraph:
Async/await and
Task
have long since replaced APM. These days the standard pattern for work that is inherently blocking is to do it on a non-UI thread, typically on a thread pool thread usingTask.Run
. It's pretty easy to send updates to the UI thread from the worker thread once you know what to use, such System.Progress and SynchronizationContext.Post.Since I want to run this in an app that does not depend on Windows Forms, I removed Application.DoEvents and moved the work to the background thread. There was a nice seam between the UI code and the conversion code so that I was able to add a single
Await Task.Run
to do the move.➡ I ran the program before and after this change on https://github.com/nunit/nunit/blob/master/src/NUnitFramework/framework/nunit.framework.csproj. I could not tell a difference in program behavior. If you find a difference, I'm interested to fix it.
Commits
Marshal progress updates from any thread safely to the UI thread
Use Using block to dispose variable even if an exception is thrown first
Use System.Progress to allow progress to be safely reported from any thread
TextProgressBar should no longer implement System.IProgress directly because this forces System.Progress to be used, enabling updates safely from any thread
Use clearer name now that TextProgressBar does not implement System.IProgress
Marshal exception reporting from any thread safely to the UI thread
Move conversion work to a background thread
Run conversion process on a non-UI thread
ByRef not allowed in async methods, refactor