使用任务并行库 (TPL) 进行轮询

Posted

技术标签:

【中文标题】使用任务并行库 (TPL) 进行轮询【英文标题】:Using task parallel library (TPL) for polling 【发布时间】:2015-07-27 18:06:39 【问题描述】:

我是 C# 新手,我有一个设备(外围设备),我需要从 C# 控制台应用程序通过串行/USB 进行轮询。虽然下面的代码显然没有抛出任何异常(错误),也没有执行轮询。会发生什么?谢谢。

控制台输出为:

Here goes...
t1: System.Threading.Tasks.Task

PD。从调试中,我的印象是 while(true) ... 块没有运行。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using T1NET;

namespace ValController

    class Program
    
        static void Main(string[] args)
        

            T1NET.comm Device = new T1NET.comm();
            bool devfound = true;
            Device.Port = new T1NET.COM_port();
            Device.Port.RtsEnable = false;
            Device.HandlePort = true;
            Device.Port.BaudRate = 9600;
            Device.Port.PortName = "COM4";
            Device.Device = T1NET.Device.Valid;
            Device.Port.ReadTimeout = 100;

            if (devfound)
            
                BV_Device.HandlePort = true;
                Console.WriteLine("here goes...");
                var t1 = Task.Factory.StartNew(() =>
                
                    while (true)
                    
                        System.Threading.Thread.Sleep(100);
                        System.Threading.Thread.BeginCriticalRegion();
                        T1NET.Answer answer = Device.RunCommand(T1NET.T1NETCommand.Poll);
                        Console.WriteLine("answer:" + answer);
                    
                );

                Console.WriteLine("t1: " + t1);

            
        
    

【问题讨论】:

while 不执行的唯一方法是任务永远不会启动(请参阅***.com/questions/12010131/…)。如果不是这种情况,请尝试在您的 while 循环中的 answer = ... 语句之前放置一个中断,它会被多次击中吗?您的任务可能会在第一次执行时无限期地等待答案。 等等...我刚刚意识到你启动了一个异步任务然后程序结束了。尝试等待任务完成。 嗨弗拉德,谢谢,但它的行为方式是一样的。 尝试在 if (devfound) 块的末尾添加 t1.Wait() 感谢您的评论!它正在循环工作......唯一似乎不起作用的是轮询线。 【参考方案1】:

在您的示例中,您启动了一个新的异步任务,同时您的应用程序继续执行到 Main 方法的末尾,并在您的新任务甚至有机会执行其内容之前突然退出(在你的情况,while loop)。

你需要等待你的任务完成(或者在你的情况下,执行直到你杀死它)。尝试像这样构建您的代码:

static void Main(string[] args)

    //// Your initialization code

   if (devfound)
   
        //// Device found, prepare for task
        var t1 = Task.Factory.StartNew(() =>
        
            //// Task body
        );

        t1.Wait();
   

【讨论】:

感谢您的详细实施。【参考方案2】:

每当您进行异步编程,并且您在执行其他操作时启动了一个单独的任务来执行操作,那么您应该在某个时间位置等待其他任务的结果。

通常你不知道其他任务什么时候开始,除非你开始摆弄优先级和其他东西。由操作系统决定在您的哪个语句之后另一个任务开始。因此,在对自己进行一些处理之后,您永远无法确定其他任务是否已经开始以及它已经完成了什么,除非您开始等待其他任务的一些生命迹象。

你可以检查其他任务的状态,但是你只知道它是否开始运行,也许它只执行了第一条语句。你永远无法确定它何时会执行下一个语句。

了解其他任务状态的正确方法: - 等待它完成。如果您只需要结果,则很有用 - 等待一些信号量/事件/等发出信号。如果您需要随时了解其他任务的进度,这很有用

【讨论】:

您好 Harald,感谢您的 cmets。当我在这个项目中取得进展时,我会牢记它们。

以上是关于使用任务并行库 (TPL) 进行轮询的主要内容,如果未能解决你的问题,请参考以下文章

有没有办法将任务并行库(TPL)与 SQLDataReader 一起使用?

三分钟总览微软任务并行库TPL

理解并行编程

如何在通用应用程序中禁用任务并行库的 ETW EventSource?

使用任务并行库的更好方法是啥

多线程编程学习笔记——任务并行库