Обновление пользовательского интерфейса после запуска фоновой работы с параллельным. Invoke - PullRequest
2 голосов
/ 17 декабря 2010

Я выполняю тяжелую фоновую работу с Parallel.Invoke, после того как вся обработка завершена, я возвращаю метод, возвращаюсь снова, вызываю следующий метод, чтобы использовать вычисленные данные, я получаю ошибку: Недопустимая операция между потоками: доступ к элементу управления '' осуществляется из потока, отличного от потока, в котором он был создан.

Но я уже вернулся из потоков, которые были созданы Parallel.Invoke, к тому, который вызвал его в первую очередь. Это нормально, что управление не возвращается к потоку, где оно началось? И как я могу гарантировать, что это произойдет?

Код:

public void TopMethod()
        {
            Calculate(4);
            UpdateGui();
        }

        public void Calculate(int depth)
        {
            Recursive(depth);
        }

        public void Recursive(int depth)
        {
            if (depth > 0)
                System.Threading.Tasks.Parallel.Invoke(
                            delegate { Recursive(depth - 1); });
        }

        public void UpdateGui()
        {
            CalculateOhter(); // Works fine.
            controlElement.Focus(); // Causes exception
        }

Изменения: Я знаю о Control.Invoke Но это было бы уродливым решением (не хочу хранить делегат в каждом элементе управления), и программе нужно дождаться завершения всех вычислений, прежде чем она сможет продолжить. Поэтому было бы лучше, если бы я мог каким-то образом заставить управление вернуться к тому потоку, с которого я начал.

Ответы [ 4 ]

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

Вам необходимо получить доступ к элементу управления / окну из потока, создавшего этот элемент управления.Используйте Control.Invoke и Control.InvokeRequired .

0 голосов
/ 20 декабря 2010

Решил, оказалось, что я создал отдельный поток для вызова данного кода в первую очередь, довольно глупо: P

0 голосов
/ 17 декабря 2010

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

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

Я не понимаю, почему это не происходит по умолчанию, почему он не просто возвращается к потоку, с которым он начал, когда все завершено?

0 голосов
/ 17 декабря 2010

Ужасный способ сделать это установить Control.CheckForIllegalCrossThreadCalls в false. Он должен избавиться от вашей ошибки, но это не очень хороший дизайн.

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

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