Задать вопрос
Dyikot
@Dyikot

Почему при попытке в многопоток у меня выполняется все либо также либо дольше?

Хочу выполнить на нескольких потоках следующее: обновлять нумерацию после добавления строк в DataGridView. И получается чем больше строк тем дольше это делается. Например при добавлении 100 строк затрачено около 800 мс, и получается если уже 100 есть и еще добавить 100, то процесс еще затягивается в 2 раза, как я понял из-за перевода int в string тратится примерно половина и далее и больше времени.
И так как задачи независимы хочется их распаралеллить. Т.е условно если 2 потока, то один делает одну половину а второй другую, если 4 то каждый делает свои 25%.

Я применял несколько способов, но навернека что-то недопонял и работает не так как должно.
В один поток
for (int i = rowCountBeforeAdd; i < e.RowCount + rowCountBeforeAdd; i++)
            dataGridView.Rows[i].HeaderCell.Value = (i + 1).ToString();

ParallerFor
int[] interval = new int[5];

for (int i = 0; i < interval.Length; i++)
            interval[i] = (e.RowCount * i) / (interval.Length - 1);

Parallel.For(0, interval.Length - 1, (taskNumber) =>
{
         for (int i = interval[taskNumber]; i < (interval[taskNumber + 1] + rowCountBeforeAdd); i++)
                     dataGridView.Rows[i].HeaderCell.Value = (i + 1).ToString();
});

Task.WhenAll (вариант 1 , выдающий исклющение)

Ислючение IndexOutOfRangeException: Index was outside the bounds of the array.
int[] interval = new int[5];

for (int i = 0; i < interval.Length; i++)
            interval[i] = (e.RowCount * i) / (interval.Length - 1);

List<Task> tasks = new List<Task>();

for (int j = 0; j < interval.Length - 1; j++)
{
       tasks.Add(Task.Run(() =>
      {
              for (int i = rowCountBeforeAdd + interval[j]; i < interval[j + 1] + rowCountBeforeAdd; i++)
                          dataGridView.Rows[i].HeaderCell.Value = (i + 1).ToString();
      }));
}

await Task.WhenAll(tasks.ToArray());

Task.WhenAll (без искл. но и без цикла)

int[] interval = new int[5];

for (int i = 0; i < interval.Length; i++)
      interval[i] = (e.RowCount * i) / (interval.Length - 1);

Task[] tasks = new Task[4]
{
          Task.Run(() =>
          {
                for (int i = rowCountBeforeAdd + interval[0]; i < interval[1] + rowCountBeforeAdd; i++)
                                    dataGridView.Rows[i].HeaderCell.Value = (i + 1).ToString();
          }),
          Task.Run(() =>
          {
                     for (int i = rowCountBeforeAdd + interval[1]; i < interval[2] + rowCountBeforeAdd; i++)
                                dataGridView.Rows[i].HeaderCell.Value = (i + 1).ToString();
          }),
          Task.Run(() =>
          {
                 for (int i = rowCountBeforeAdd + interval[2]; i < interval[3] + rowCountBeforeAdd; i++)
                             dataGridView.Rows[i].HeaderCell.Value = (i + 1).ToString();
           }),
           Task.Run(() =>
           {
                  for (int i = rowCountBeforeAdd + interval[3]; i < interval[4] + rowCountBeforeAdd; i++)
                                    dataGridView.Rows[i].HeaderCell.Value = (i + 1).ToString();
           })
};
await Task.WhenAll(tasks);



Иногда выдают исключение, когда я например добавляю сразу 50 строк, но при если добавлять 10 то нету:
AggregateException: One or more errors occurred. (Cross-thread operation not valid: Control '' accessed from a thread other than the thread it was created on.)
InvalidOperationException: Cross-thread operation not valid: Control '' accessed from a thread other than the thread it was created on.

Код пишется тут:
dataGridView.RowsAdded += async (o, e) =>
{
//code
}
  • Вопрос задан
  • 69 просмотров
Подписаться 1 Простой Комментировать
Решения вопроса 1
petermzg
@petermzg
Самый лучший программист
Так как тут UI вам нужен всего один поток и выключение обновлений контрола до завершения операции.
Так что используйте VirtualMode как тут
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы