Как читать ListView с помощью многопоточности

Я хочу прочитать список в форме.

Моя цель - позволить программе прочитать первые 3 строки, затем она должна спать несколько миллисекунд (случайно), а затем она должна использовать следующие 3 строки, пока не будут использованы все элементы списка.

Я пробовал так, но программа всегда проверяла весь список после задержки первых 3-х строк.

List<Task> Tasklist = new List<Task>();
            List<ListViewItem> lit = new List<ListViewItem>();

int aktuellethreads = 0;
int maximalethreads = 3;

            this.Invoke(new Action(() =>
            {
                foreach (ListViewItem itt in listView1.Items)
                {
                    lit.Add(itt);
                }
            }));

            foreach (ListViewItem i in lit)
            {
                if (aktuellethreads < maximalethreads)
                {
                    Task t = Task.Run(() =>
                    {
                        Random rnd = new Random();
                        Thread.Sleep(rnd.Next(300, 10000));
                    });
                    Tasklist.Add(t);
                    aktuellethreads++;
                }
                    if(aktuellethreads >= maximalethreads)
                    {
                    Task.WaitAny(Tasklist.ToArray());
                    aktuellethreads--;
                     }
             }

person Joe Manston    schedule 05.06.2017    source источник
comment
Посмотрите этот пост на здесь. (Я не могу комментировать это из-за низкой репутации).   -  person fluffy    schedule 05.06.2017
comment
Ну, что это явно должно делать? Потому что этот код, кажется, просто загружает сразу все элементы от listView1 до lit, а затем повторяет lit с задачами. Таким образом, в этих итерациях он будет перебирать первые 3 элемента только в начале, остальные будут перебираться, если какая-либо из задач освободится, одна за другой, а не партиями по 3.   -  person Dominik Szymański    schedule 05.06.2017
comment
Да, вы правы, Доминик, но как мне сделать так, чтобы он делал каждый раз только 3 элемента?   -  person Joe Manston    schedule 05.06.2017
comment
Может, попробовать WaitAll? После этого очистите Tasklist и aktuellethreads. Ну, даже нет, это не будет работать на 100%, потому что вы берете 4-й элемент как раз тогда, когда ждете завершения задачи. Я напишу правильный ответ через минуту.   -  person Dominik Szymański    schedule 05.06.2017
comment
Не очень хорошо иметь несколько потоков, взаимодействующих с пользовательским интерфейсом. Вы ничего не покупаете себе, делая это с потоками в любом случае.   -  person Cody Gray    schedule 05.06.2017


Ответы (1)


Чтобы сделать это правильно, вы должны изменить свой подход к проверке.

List<Task> tasklist = new List<Task>();
List<ListViewItem> lit = new List<ListViewItem>();

int maximalethreads = 3;

this.Invoke(new Action(() =>
{
    foreach (ListViewItem itt in listView1.Items)
    {
        lit.Add(itt);
    }
}));

foreach (ListViewItem i in lit)
{
    Task t = Task.Run(() =>
    {
        Random rnd = new Random();
        Thread.Sleep(rnd.Next(300, 10000));
    });
    tasklist.Add(t);

    if(tasklist.Count >= maximalethreads)
    {
        Task.WaitAll(tasklist.ToArray());
        tasklist.Clear();
    }
}

Это должно работать, я не уверен на 100% в синтаксисе, так как я написал этот код в поле ответа SO, но я думаю, что это работает.

person Dominik Szymański    schedule 05.06.2017