Вызов обновления WPD ProgressBar внутри делегата QueuedAsMacro - PullRequest
0 голосов
/ 05 ноября 2019

Я использую ExcelDNA для чтения данных из рабочих книг (используя C API) внутри асинхронного диалога WPF. Чтобы это работало, я использую делегат QueuedAsMacro. Проблема в том, что я хочу обновить индикатор выполнения, и поэтому я пытаюсь использовать BackgroundWorker (когда я новичок в многопоточности), но это не удается, выдавая следующую ошибку:

Эта операция уже вызывала OperationCompleted, и дальнейшие вызовы являются недопустимыми.

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

Следует фрагмент кода:

        private void MyMainFunction(object sender, DoWorkEventArgs e)
        {
            ExcelAsyncUtil.QueueAsMacro(
                delegate
                {
                    float i = 0;
                    foreach (wkbData iWbk in wkbsList)
                    {
                        ReadWorkbookData(iWbk );
                        i++;
                        (sender as BackgroundWorker).ReportProgress(Convert.ToInt16((i / wkbsList.Count) * 100)); //Update progress bar
                    }
                });
        }

Я также пытался использовать делегат Invoke (просто выстрел в темноте). Но результаты остаются прежними:

this.Dispatcher.Invoke(() => { (sender as BackgroundWorker).ReportProgress(Convert.ToInt16((i / wkbsList.Count) * 100)); });

Другими словами: выполняя некоторые тесты, я понял, что индикатор выполнения работает нормально, если я не использую ExcelAsyncUtil.QueueAsMacro. делегат.

Кроме того, как только QueueAsMacro отклоняет выполнение другим потоком, использование BackgroundWorker просто не соответствует моей проблеме, например, событие RunWorkerCompleted запускается беззавершение методов внутри ExcelAsyncUtil.QueueAsMacro.

Я совершенно уверен, что мне нужно найти способ связи потока QueuedAsMacro с потоком WPF, но я понятия не имею, как это сделать.

Любая подсказка?

Обновление благодаря некоторым новым тестам и исследованиям:

QueuedAsMacro позволяет обновлять индикатор выполнения непосредственно в потоке WPF, еслиВы используете Invoke делегат. (без необходимости использования какой-либо стратегии, такой как событие ProgressChanged BackgroundWorker).

Dispatcher.Invoke(() => MyProgressBarControl.Value = Convert.ToInt16((i / wkbsList.Count) * 100));

Тем не менее, обновляется только значение индикатора выполнения (сама панель не получает цветовой окраски).

Я только что случайно обнаружил, что использование BackgroundWorker просто для вызова основной функции (bgWorker.DoWork += MyMainFunction) и непосредственного обновления индикатора выполнения дает ожидаемый результат: плавное выполнение, в том числе рисование.

Это действительно странно, и у меня нет объяснения этому. Я надеюсь, что кто-то может уточнить.

Заранее спасибо.

...