Parallel.Invoke和Dispatcher.Invoke

时间:2017-10-14 05:02:31

标签: c# wpf multithreading task-parallel-library dispatcher

我对WPF和并行处理相当新。我已经将一个简单的程序从Console应用程序转换为WPF。我想要并行执行的函数很少。下面的代码在Console应用程序中运行良好。

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中使用相同的内容时,我会得到异常 -

  

调用线程无法访问此对象,因为它不同   线程拥有它

所以我根据其他Stackoverflow帖子中的建议使用了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中被无限地卡住了。搜索后,我遇到了这个链接 - Cannot use Dispatcher.Invoke in Parallel.Invoke,这似乎是一个死锁问题。

我知道我可以在单独的变量中分配文本框值并将它们作为参数传递然后使用Parallel.Invoke但如果我不使用这些变量会有什么解决方法?

有人可以建议一个正确的解决方法吗?

2 个答案:

答案 0 :(得分:0)

没有直接在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);

答案 1 :(得分:0)

Parallel.Invoke方法阻止调用线程,直到所有操作都将完成。如果您从UI线程调用Parallel.Invoke,然后在内部Parallel.Invoke中使用试图调用UI线程的Dispatcher.Invoke,则将死锁,因为Parallel.Invoke方法将无法完成。可能的解决方案是将Parallel.Invoke包装在Task.Run中以释放UI线程。