Parallel.Invoke 和 Dispatcher.Invoke 之间的死锁
Deadlock between Parallel.Invoke and 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 中使用它时,出现异常-
The calling thread cannot access this object because a different
thread owns it
所以我根据其他 Whosebug 帖子的建议使用了 Dispather.Invoke-
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 中。搜索后,我发现了这个 link- Cannot use Dispatcher.Invoke in Parallel.Invoke,这似乎是一个死锁问题。
我知道我可以在单独的变量中分配文本框值并将它们作为参数传递,然后使用 Parallel.Invoke 但是如果我不使用变量会有什么解决方法?
有人可以建议解决此问题的正确方法吗?
没有直接在 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);
Parallel.Invoke 方法阻塞调用线程,直到所有操作完成。如果您从 UI 线程调用 Parallel.Invoke,然后在 Parallel.Invoke 内部使用 Dispatcher.Invoke 尝试调用 UI 线程,您将陷入死锁,因为 Parallel.Invoke 方法将无法完成。可能的解决方案是将 Parallel.Invoke 包装在 Task.Run 中以减轻 UI 线程。
我对 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 中使用它时,出现异常-
The calling thread cannot access this object because a different thread owns it
所以我根据其他 Whosebug 帖子的建议使用了 Dispather.Invoke-
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 中。搜索后,我发现了这个 link- Cannot use Dispatcher.Invoke in Parallel.Invoke,这似乎是一个死锁问题。
我知道我可以在单独的变量中分配文本框值并将它们作为参数传递,然后使用 Parallel.Invoke 但是如果我不使用变量会有什么解决方法?
有人可以建议解决此问题的正确方法吗?
没有直接在 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);
Parallel.Invoke 方法阻塞调用线程,直到所有操作完成。如果您从 UI 线程调用 Parallel.Invoke,然后在 Parallel.Invoke 内部使用 Dispatcher.Invoke 尝试调用 UI 线程,您将陷入死锁,因为 Parallel.Invoke 方法将无法完成。可能的解决方案是将 Parallel.Invoke 包装在 Task.Run 中以减轻 UI 线程。