This is not safe. The UI thread could (and probably will) change the state of the control while you are reading it from another thread. Your reads might catch the control in a half-baked state. It may appear to be working now, but sooner or later it will fail...probably unpredictably and spectacularly.
No, you probably do not need to use the Invoke pattern. To be quite frank...that pattern is usually the worst option. It is usually better to have your worker thread do the heavy lifting and then send new data or progress information to the UI thread via a queue and let the UI thread pick this up via a timer. This has several advantages.
- Eliminates the expensive
Invoke and BeginInvoke operations.
- The UI thread gets to decide when and how often it should update itself with new data instead of having the worker thread dictate this.
- You get more throughput on the worker thread since it doesn't have to wait for
Invoke to return.
- There is no risk of overrunning the UI message queue like there would be with
BeginInvoke.
- It decouples the UI and worker thread interactions.
You will need to enumerate the ListView and build up a separate data structure that can then be accessed by the worker thread safely. If the ListView contains a lot of items consider maintaining a separate collection in tandem with the control. That way you spread out the penalty of coping the data over a bigger period of time in which it probably will not be noticed as much. Afterall, we do not want the copy operation to freeze the UI thread otherwise a user will notice. A ConcurrentBag or the like might be a good choice since it can be safely modified by the UI thread while the worker thread is reading it.