大佬教程收集整理的这篇文章主要介绍了c# – WPF,TPL,生产者/消费者模式 – 错误的线程错误,大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
感谢您的任何帮助!
BlockingCollection<String> blockingCollection = new BlockingCollection<String>(); CancellationToken token = tokensource.Token; Taskscheduler uischeduler = Taskscheduler.FromCurrentSynchronizationContext(); Task task1 = new Task( (obj) => { for (int i = 0; i < 10; i++) { if (token.IsCancellationrequested) { TxtBlock2.Text = "Task cancel detected"; throw new operationCanceledException(token); } else { String code = i.ToString() + "\t" + AsynchttpReq.get_source_Webrequest(uri); blockingCollection.Add(codE); } } },Taskscheduler.Default); task1.ConTinueWith(antecedents => { TxtBlock2.Text = "Signalling production end"; blockingCollection.CompleteAdding(); },uischeduler); Task taskCP = new Task( (obj) => { while (!blockingCollection.IsCompleted) { String dlCode; if (blockingCollection.TryTake(out dlCodE)) { //the calling thread cAnnot access this object because a different thread owns it. TxtBlock3.Text = dlCode; } } },uischeduler); WindowsBase.dll!Sy@R_403_2407@.Windows.Threading.Dispatcher.VerifyAccess() + 0x4a bytes WindowsBase.dll!Sy@R_403_2407@.Windows.DependencyObject.SETVALue(Sy@R_403_2407@.Windows.DependencyProperty dp,object value) + 0x19 bytes PresentationFramework.dll!Sy@R_403_2407@.Windows.Controls.TextBlock.Text.set(String value) + 0x24 bytes
system.invalidoperationException was unhandled by user code message=The calling thread cAnnot access this object because a different thread owns it. source=WindowsBase StackTrace: at Sy@R_403_2407@.Windows.Threading.Dispatcher.VerifyAccess() at Sy@R_403_2407@.Windows.DependencyObject.SETVALue(DependencyProperty dp,Object value) at Sy@R_403_2407@.Windows.Controls.TextBlock.set_Text(String value) at WpfRibbonApplication4.MainWindow.<>c__DisplayClass5.<Button1_Click>b__3(Object o) in C:\ ... \WpfRibbonApplication4\WpfRibbonApplication4\MainWindow.xaml.cs:line 90 at Sy@R_403_2407@.Threading.Tasks.Task.InnerInvoke() at Sy@R_403_2407@.Threading.Tasks.Task.Execute() InnerException:
谢谢你的所有帮助.
我还有两个问题:
我用Task.Factory.StartNew重写了我的代码.但是我的Task2似乎会引起问题.没有错误消息.看起来很像一个紧凑的循环.当然,我没弄清楚为什么?
你会这么善良并再次指出我正确的方向吗?
请记住,我已经做了大约6个月的C#和一周的TPL,否则我不会再问你了.但凭借这些经验……
再次感谢你!
Brians代码:
var task1 = new Task( (obj) =>
为什么需要obj?
private void Button1_Click(object sender,RoutedEventArgs E) {
Taskscheduler uiTaskscheduler = Taskscheduler.FromCurrentSynchronizationContext();
BlockingCollection blockingCollection = new BlockingCollection();
CancellationTokensource cts = new CancellationTokensource();
CancellationToken token = cts.Token; Task task1 = Task.Factory.StartNew( () => { for (int i = 0; i < 10 ; i++) { token.ThrowIfCancellationrequested(); String code = i++.ToString() + "\t" + AsynchttpReq.get_source_Webrequest(uriDE); blockingCollection.Add(codE); } },token,TaskCreationOptions.None,Taskscheduler.Default); task1.ConTinueWith( (antecedents) => { if (token.IsCancellationrequested) { TxtBlock2.Text = "Task cancel detected"; } else { TxtBlock2.Text = "Signalling production end"; } blockingCollection.CompleteAdding(); },uiTaskscheduler); Task task2 = Task.Factory.StartNew( () => { while (!blockingCollection.IsCompleted) { String dlcode; if (blockingCollection.TryTake(out dlcodE)) { TxtBlock3.Text = dlcode; } } },uiTaskscheduler); }
通常人们使用Task.Factory.StartNew,所以我甚至没有注意到你手动构建任务.手动构造Task实例时,指定调度程序以运行它们的正确方法是使用带有Taskscheduler实例的Start重载.所以在你的情况下你需要做:
taskCP.Start(uiTaskscheduler);
好的,现在你的更新代码的问题是你已经有效地安排了一个在UI(调度程序)线程上的任务,它坐在那里紧紧地循环阅读.
现在代码被重做了,很明显你不想在UI线程上安排task2.如果要将通知从那里推送到UI,您可以按照另一个答案的建议调用Dispatcher :: BeginInvoke,也可以使用循环内部的uiTaskscheduler启动新任务.调用Dispatcher :: BeginInvoke将减少开销,并且更清晰的代码恕我直言,所以我建议只是这样做.
以上是大佬教程为你收集整理的c# – WPF,TPL,生产者/消费者模式 – 错误的线程错误全部内容,希望文章能够帮你解决c# – WPF,TPL,生产者/消费者模式 – 错误的线程错误所遇到的程序开发问题。
如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。