C # 4.0 Доступ к элементу управления формы из Parallel.ForEach - PullRequest
2 голосов
/ 18 декабря 2010

Код ниже работает нормально.Интересно, действительно ли это правильно?

if (openFileDialog.ShowDialog() == DialogResult.OK)
{
    Parallel.ForEach(openFileDialog.FileNames, currentFile =>
    {
       try
       {
           StreamReader FileReader = new StreamReader(currentFile);
           do
           {
               URLtextBox.Invoke(new MethodInvoker(delegate
               {
                   URLtextBox.Text += SelectURLfromString(FileReader.ReadLine());
               }));
           }
           while (FileReader.Peek() != -1);
           FileReader.Close();
        }
        catch (System.Security.SecurityException ex)
        {
            ...
        }
        catch (Exception ex)
        {
            ...
        }
     });
}

В противном случае я получаю либо «Операция с несколькими потоками недопустима. Управление« URLtextBox », доступ к которой осуществляется из другого потока», либо зависание приложения.

Ответы [ 4 ]

5 голосов
/ 18 декабря 2010

Код правильный - вам нужно использовать Invoke для обновления элементов управления вне потока GUI. Однако вы также исключаете метод SelectURLfromString(FileReader.ReadLine()); в потоке GUI, его следует заменить на

   string url = SelectURLfromString(FileReader.ReadLine());
   URLtextBox.Invoke(new MethodInvoker(delegate
   {
       URLtextBox.Text += url;
   }));

, чтобы свести к минимуму работу в потоке GUI.

2 голосов
/ 18 декабря 2010

Код правильный, вам нужен вызов Invoke, чтобы элемент управления обновлялся в потоке GUI.

Однако, есть некоторые другие вещи, которые не имеют смысла в коде:

  • Вы выполняете параллельные операции, которые используют ресурс, который не является параллельным. Ваши темы будут бороться за внимание со стороны диска, который, очевидно, является горлышком бутылки из-за его относительно низкой скорости.

  • Вы будете читать строки из нескольких файлов и помещать их в текстовое поле. Это может быть хорошо в этой конкретной ситуации, но в целом это дает непредсказуемый результат.

  • Вы используете операцию += для объединения строк, метод, который известен своей плохой масштабируемостью. Это не может быть большой проблемой в этом случае, так как горлышко диска диска, вероятно, намного хуже.

2 голосов
/ 18 декабря 2010

Вы не можете безопасно обновлять элементы управления пользовательского интерфейса из рабочих потоков, если не выполните маршалинг в поток пользовательского интерфейса.

Взгляните на TaskScheduler.FromCurrentSynchronizationContext

Какпланировать работу в указанном контексте синхронизации

1 голос
/ 18 декабря 2010

Invoke необходим, потому что элементы управления связаны с потоком, который создал их связанное окно User32 (часто называемое HWND). Тем не менее, вы, вероятно, могли бы немного оптимизировать, читая и обрабатывая содержимое файла вне делегата Invoke.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...