Nano Hash - криптовалюты, майнинг, программирование

Тупик между Parallel.Invoke и Dispatcher.Invoke

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

long primeP;
string[] arrIDsP = null;
string[] arrNamesP = null;
string[] arrMergedP = null;

Parallel.Invoke(
    () => primeP = this.FindPrimeNumber(Convert.ToInt64(txtPrime.Text)),
    () => arrIDsP = this.FetchData(@txtFilePath1.Text),
    () => arrNamesP = this.FetchData(@txtFilePath2.Text));

arrMergedP = this.MergeIDToNameP(arrIDsP, arrNamesP);

Когда я использую то же самое в WPF, я получаю исключение:

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

Поэтому я использовал Dispather.Invoke в соответствии с предложениями в других сообщениях Stackoverflow.

Parallel.Invoke(
    () => primeP = this.FindPrimeNumber(this.Dispatcher.Invoke(() => Convert.ToInt64(txtPrime.Text))),
    () => arrIDsP = this.FetchData(this.Dispatcher.Invoke(() => @txtFilePath1.Text)),
    () => arrNamesP = this.FetchData(this.Dispatcher.Invoke(() => @txtFilePath2.Text)));

arrMergedP = this.MergeIDToNameP(arrIDsP, arrNamesP);

Теперь проблема в том, что мой код бесконечно застревает внутри Parallel.Invoke. После поиска я наткнулся на эту ссылку: ?forum=csharplanguage" rel="nofollow noreferrer">Невозможно использовать Dispatcher.Invoke в Parallel.Invoke, и это похоже на тупиковую ситуацию.

Я знаю, что могу присвоить значения текстового поля отдельным переменным и передать их в качестве параметров, а затем использовать Parallel.Invoke, но что было бы обходным путем, если бы я не использовал переменные?

Может ли кто-нибудь предложить правильный способ решить эту проблему?


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

Ответы:


1

На WPF напрямую не работал, но ошибка явно показательна. Поскольку каждый параметр Parallel.Invoke выполняется в потоке, попробуйте получить доступ к значениям из пользовательского интерфейса WPF (например, textPrime.Text) вне этих потоков.

long primeP;
string[] arrIDsP = null;
string[] arrNamesP = null;
string[] arrMergedP = null;

string prime = txtPrime.Text;
string filePath1 = txtFilePath1.Text;
string filePath2 = txtFilePath2.Text;

Parallel.Invoke(
    () => primeP = this.FindPrimeNumber(Convert.ToInt64(prime)),
    () => arrIDsP = this.FetchData(filePath1),
    () => arrNamesP = this.FetchData(filePath2));

arrMergedP = this.MergeIDToNameP(arrIDsP, arrNamesP);
14.10.2017
  • Я знаю, что это может сработать. Пожалуйста, смотрите мой обновленный вопрос. 14.10.2017
  • @SouvikGhosh, вы можете заставить его работать, но это ничего вам не принесет. Безопасный доступ к объектам пользовательского интерфейса из других потоков может быть выполнен только путем выполнения этих инструкций в потоке пользовательского интерфейса, это то, что может сделать Dispacher.Invoke, но он переключится с фонового потока на поток пользовательского интерфейса, что сделает ваше «параллельное» выполнение бесполезным. 14.10.2017

  • 2

    Метод Parallel.Invoke блокирует вызов потока до завершения всех операций. Если вы вызываете Parallel.Invoke из потока пользовательского интерфейса, а затем внутри Parallel.Invoke используете Dispatcher.Invoke, который пытается вызвать поток пользовательского интерфейса, вы получите взаимоблокировку, поскольку метод Parallel.Invoke не сможет завершиться. Возможное решение — обернуть Parallel.Invoke в Task.Run, чтобы разгрузить поток пользовательского интерфейса.

    10.11.2019
    Новые материалы

    Кластеризация: более глубокий взгляд
    Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

    Как написать эффективное резюме
    Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

    Как я автоматизирую тестирование с помощью Jest
    Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

    Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
    В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..