2017-02-10 2 views
0

я уже знаю, что контроль обновлять, я могу использовать Invoke ActionUpdate ListView из потока не исходный поток в C#

progressBar1.Invoke(new Action(() => { progressBar1.Maximum = 0; })); 

Но это работает только с имуществом управления, которые являются единичными данные. Теперь у меня есть поток, который должен изменить коллекцию представлений списка элементов списка, очистить его, а затем обновить новыми элементами, новыми текстами и изображениями значков. В чем разница между ними: целое число или bool сравниваются с списком, массивом или набором целочисленного, bool или даже компонента, управления. Могу ли я просто просто добавить

string[] newItemText = {"item1", "item2", ...}; 
listView1.Invoke(new Action() => { 
    i = 0; 
    foreach(var item in listView1.Items) 
    { 
     item.Text = newItemText[i]; 
     i++; 
    } 
})); 

Я, возможно, потребуется решение для моего списка зрения, но если у вас есть ответ, пожалуйста, четко объяснить, как и почему это работает, потому что мне нужно тщательно узнать об этом. Также вы можете заметить меня о риске при попытке этой практики.

EDIT: вопрос заключается не в том, как обновлять управление из других потоков. IT о том, когда и зачем нужно это делать, а не тому. Более того, мне нужно знать разные варианты обновления отдельных данных и обновления всей коллекции данных.

+1

_ «Могу ли я просто добавить» _ - что случилось, когда вы это пробовали? Как это отличалось от того, что вы хотели? Не совсем ясно, каков ваш реальный вопрос. Вы, кажется, понимаете, что вам нужно делать. Итак ... сделайте это. Если у вас есть определенные проблемы с этим, объясните, что именно эта проблема. Предоставьте хороший [mcve], показывающий точно, что вы пробовали, а также четкое подробное объяснение того, что делает код, и что вы хотите, чтобы он это сделал. –

+0

Если у вас много работы в пользовательском интерфейсе, вам нужно переосмыслить свой дизайн. Работа cpu/IO в фоновом режиме и пользовательский интерфейс работают по потоку пользовательского интерфейса как можно больше. Лучше, чем усложнять вещи. Взгляните на async/wait, это должно помочь. См. Http://blog.stephencleary.com/2012/02/async-and-await.html и проводник оттуда. –

+0

Возможный дубликат [Как обновить GUI из другого потока в C#?] (Http: // stackoverflow.com/questions/661561/how-to-update-the-gui-from-another-thread-in-c) – VMAtm

ответ

1

Нет никакой разницы в обновлении значения или добавлении большего количества элементов в список.

Что происходит внутри, так это то, что графические ресурсы, используемые для рисования в Windows (также могут применяться к Android), требуют использования ручек, кистей и таких объектов.

Эти объекты относятся к контексту потока, в котором они были созданы изначально. Обычно это происходит в основном потоке, но если вы создадите графический объект, в этом случае List, в отдельном потоке, отличном от основного, этот конкретный поток будет потоком «владельца» вашего элемента управления.

Если вы хотите что-то изменить в элементе управления, требующем обновления интерфейса (требуется использование ручек, кистей и т. Д.), Вы должны сделать это из того же потока, который «владеет» вашим элементом управления. Вот почему вам нужно использовать Invoke.

Это основной принцип. Если вы обновите скалярное значение как целое, или если вы добавите элементы в список, нет никакой разницы. Оба требуют использования графических ресурсов, поэтому оба требуют вызова из того же потока, которому принадлежит элемент управления.

Сообщите мне, если будет ясно.

Редактировать. В любом случае ваш код выглядит немного странным, потому что вы заполняете List iterating из собственного списка. Не имеет смысла делать это ?:

string[] newItemText = {"item1", "item2", ...}; 
listView1.Invoke(new Action() => { 
    for(int i = 0; i < newItemText.length; i++) 
    { 
    listView1.add(newItemText[i]); 
    } 
}); 

, не зная остальной части контекста, это звучит более логично для меня.

+0

Хорошо, если мы изменим UI, тогда он использует поток пользовательского интерфейса, который является исходным потоком пользовательского интерфейса. Но почему я ничего не меняю, просто назначаю или достигаю определенного значения, и это порождает исключение. Подобно этому элементу ListViewItem item = listView1.Items [i]; – user3505230

+0

в вашем примере вы назначаете свойство text: item.Text = newItemText [i]; И это изменяет пользовательский интерфейс. В любом случае ваш пример выглядит немного странно для меня. Я отредактирую свой пост, чтобы поставить то, что я думаю, что вам следует делать. – Fernando

+0

Ну, ваш код работает, только если он изменил вид списка один раз, что если каждый раз, когда я нажимаю кнопку, просмотр списка должен обновлять его. Поэтому проблема в том, что я не знаю, как и зачем это делать. Потому что в другом потоке мне нужно прочитать этот текст для просмотра списка. Поэтому мой основной вопрос и мой вопрос с вопросом разные. Один поток извлекает данные откуда-то, чтобы обновить представление в виде списка, другой поток извлекает текст из представления списка для другого процесса, который нужно вызвать, и вызывают недопустимую работу, несмотря на то, что я только читаю данные из своего списка в последнем. – user3505230

Смежные вопросы