Instead of tracking threads directly, the user interface is associated with an ObserveableCollection<ProgressDetail> , each of which represents progress, then in your loop it adds an element to the collection when it starts, then removes it from the collection when it ends.
One thing you must be careful about is thread safety, ObseveableCollection not thread safe, so you should only interact with it in thread safe ways, the easiest way to do this is to make all the addition and removal of ProgressDetail objects in the user interface thread. This also has the added benefit of capturing the SynchronizationContext of a user interface stream when creating a Progress object.
public ObserveableCollection<ProgressDetail> ProgressCollection {get; private set;} public void CopyFiles(string dir) { var dispatcher = Application.Current.Dispatcher; Parallel.ForEach(Directory.GetFiles(dir).ToList(), file => { ProgressDetail progressDetail = null; dispatcher.Invoke(() => {
See this answer for an XCopy example that will be copied with progress. I made the assumption that the Copy signature was changed to
public static void Copy(string source, string destination, bool overwrite, bool nobuffering, IProgress<double> handler)
but I leave this actual change as an exercise for the reader.
UPDATE: I updated the above code example to open the public ProgressPercentage property, which can be bound and trigger the correct events. I also translated listening for the Progress event into the internal elements of the ProgressDetail class.
source share