C#   发布时间:2022-04-03  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了c# – WPF,TPL,生产者/消费者模式 – 错误的线程错误大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
我是TPL和WPf的新手,有以下问题.
我尝试在无限循环中下载一个站点(这里只是for循环)和
将其添加到队列中.下一个任务将其取出并在Textblock中显示.
但是我似乎没有为UI获得正确的线程,尽管我认为我正确地使用了Taskscheduler.

感谢您的任何帮助!

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实例.没有构造函数重载需要Taskscheduler.

通常人们使用Task.Factory.StartNew,所以我甚至没有注意到你手动构建任务.手动构造Task实例时,指定调度程序以运行它们的正确方法是使用带有Taskscheduler实例的Start重载.所以在你的情况下你需要做

taskCP.Start(uiTaskscheduler);

updatE

好的,现在你的更新代码的问题是你已经有效地安排了一个在UI(调度程序)线程上的任务,它坐在那里紧紧地循环阅读.

现在代码被重做了,很明显你不想在UI线程上安排task2.如果要将通知从那里推送到UI,您可以按照另一个答案的建议调用Dispatcher :: BeginInvoke,也可以使用循环内部的uiTaskscheduler启动新任务.调用Dispatcher :: BeginInvoke将减少开销,并且更清晰的代码恕我直言,所以我建议只是这样做.

大佬总结

以上是大佬教程为你收集整理的c# – WPF,TPL,生产者/消费者模式 – 错误的线程错误全部内容,希望文章能够帮你解决c# – WPF,TPL,生产者/消费者模式 – 错误的线程错误所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。