S
S
SaimonPhoenix2015-07-02 14:14:57
WPF
SaimonPhoenix, 2015-07-02 14:14:57

How to properly populate an ObservableCollection in a loop and in a thread?

There is a DP class:

public class DP
    {
        public string Number { get; set; }
        public string MachineName { get; set; }
        public string UserName { get; set; }
        public string IPAddress { get; set; }
    }

Collection oCollectDP:
ObservableCollection<DP> oCollectDP = new ObservableCollection<DP>();

The method in which the filling occurs:
foreach (var item in lstWorkStation) //Список List<string>lstWorkStation
            {
                DP dp = new DP();
                string compName;
                new Thread(()=>
                {
                    compName = item;
                    dp.Number = oCollectDP.Count().ToString();
                    dp.MachineName = compName;
                    dp.UserName = getUserNameWMI(compName);
                    dp.IPAddress = getUserIP(compName);
                    
                    Dispatcher.Invoke(new Action(() =>oCollectDP.Add(dp)));
                }).Start();
            }

The collection is filled, but incorrectly (i.e. the entries in the dp.UserName or dp.IPAddress fields are duplicated). How to fix it?

Answer the question

In order to leave comments, you need to log in

3 answer(s)
T
Tsiren Naimanov, 2015-07-02
@ImmortalCAT

look at the getUserNameWMi and getUserIP methods
and why do you need a stream?
Moreover, the process of creating a thread is resource-intensive and is not immediately created in the thread pool.
try async/await
but definitely remove thread creation threads
are good if they need to use mat solutions that freeze the GUI or the main thread.
1. remove thread creation
2. look at getUserNameWMI getUserIP methods

S
SaimonPhoenix, 2015-07-02
@SaimonPhoenix

Решил сделать так:

Parallel.ForEach(lstWorkStation, currItem =>
            { 
                DP dp = new DP();

                dp.Number = oCollectDP.Count.ToString();
                dp.MachineName = currItem;
                dp.UserName = getUserNameWMI(currItem);
                dp.IPAddress = getUserIP(currItem);

                Dispatcher.Invoke(new Action(() =>
                {
                    oCollectDP.Add(dp);
                    (sender as BackgroundWorker).ReportProgress(i);
                }));
                i++;
            });

Корректно ли это?

L
Larry Underwood, 2015-07-06
@Hydro

new Thread().Start() здесь лишний.
i++ нигде не юзается.
Dispatcher.Invoke(new Action(() =>
{
if (oCollectDP.Any(e => e.UserName != dp.UserName && e.IpAddress != dp.IpAddress )) // чтобы избежать дублирования
oCollectDP.Add(dp);
(sender as BackgroundWorker).ReportProgress(i);
}));

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question