You can have a permanently working thread which is driven by the blocking queue/collection. You feed, for example, URLs to it, and it gives you downloading images on output, in a regular, non-blocking queue. This way, if you don't have a task for this thread, it will spend zero CPU time, waiting in a wait state.
I described all this in my article
Simple Blocking Queue for Thread Communication and Inter-thread Invocation[
^].
You don't need to use my queue class, because you can use the template class
System.Collections.Concurrent.BlockingCollection<>
, if your target .NET version is 4.0 or later:
BlockingCollection(T) Class (System.Collections.Concurrent)[
^].
The value of my article is that explain the principles of operation and important use cases in detail.
Now,
Windows.Forms.ListBox
is not designed to show any images. If you completely override its graphic rendering, but it would defeat the purpose of using this class completely. Therefore, you need to use something else. One suitable control which can show image would be
System.Windows.Forms.ListView
:
ListView Class (System.Windows.Forms)[
^].
Now you can use the UI without freezing. At first, you can show some predefined "image-is-not-yet-ready" image in the list view. As images are downloaded, you can replace the predefined images with the downloaded ones as they are ready. How? You cannot call anything related to UI from non-UI thread. Instead, you need to use the method
Invoke
or
BeginInvoke
of
System.Windows.Threading.Dispatcher
(for both Forms or WPF) or
System.Windows.Forms.Control
(Forms only).
You will find detailed explanation of how it works and code samples in my past answers:
Control.Invoke() vs. Control.BeginInvoke(),
Problem with Treeview Scanner And MD5.
See also more references on threading:
.NET event on main thread,
How to get a keydown event to operate on a different thread in vb.net,
Control events not firing after enable disable + multithreading.
—SA