使用任务运行连续线程

本文关键字:连续 线程 运行 任务 | 更新日期: 2023-09-27 18:32:25

我想连续运行一个线程。此线程将轮询并检查卡状态。下面是一个示例实现:

static void Main(string[] args)
        {
           var _cancelationTokenSource = new CancellationTokenSource();
           new Task(() => chkRequestTask(_cancelationTokenSource), _cancelationTokenSource.Token, TaskCreationOptions.LongRunning).Start();
           while (true)
           {
           }
        }
static bool chkRequestTask(CancellationTokenSource _cancellationTokenSource)
    {
        bool noRequest = false;
        while (!_cancellationTokenSource.Token.IsCancellationRequested)
        {
            var RequestTask = Task.Factory.StartNew(() => noRequest = chkRequestTask(_cancellationTokenSource), _cancellationTokenSource.Token);
            if (noRequest)
            {
                _cancellationTokenSource.Token.WaitHandle.WaitOne(15000);
                Console.WriteLine("Waiting for 15Seconds");
            }
            else
            {
                Console.WriteLine("Checking the card");
            }

        }
        return noRequest;
    }

我在这里想要实现的是chkRequestTask应该在单独的线程上运行。这将持续轮询卡的状态。对于此示例,我只是在做:Console.WriteLine("Checking the card");

一旦它检查了卡的状态,它应该

只在这个样本中休眠 15 秒(一般来说,它应该每 50 毫秒检查一次,但出于测试目的,我保留了 15 秒)。

但在上面的示例中,它不是睡觉,它只是不断地给我Checking the card。它根本没有睡15秒。这段代码有什么问题?

使用任务运行连续线程

你使用根本不需要的Task.Factory.StartNew递归调用chkRequestTask

目前尚不清楚为什么需要轮询状态,更好的主意是检查您正在谈论的卡 API 提供的任何事件或回调或WaitHandle。这应该让你远离痛苦。

如果您认为轮询是您剩下的唯一选择,则可以执行以下操作。

static async Task ChkRequestTask(CancellationToken token)
{
    while (true)
    {
        token.ThrowIfCancellationRequested();
        Console.WriteLine("Checking the card");
        bool status = PollTheCardForStatus();
        if(!status)
            break;
        await Task.Delay(15 * 1000, token);//Adjust the delay as you wish
    }
}

否则在代码中,如果可能的话等待调用,如果没有,则附加延续或使用阻塞task.Wait

await ChkRequestTask(token);

此方法不需要返回 bool,因为您仅在该方法为 false 时才从该方法返回,可以安全地假设从 ChkRequestTask 返回的Task完成时状态为 false,这意味着轮询返回 false 或取消CancellationToken,在这种情况下,您将获得TaskCanceledException

这就是我这样做的方式。它似乎工作正常。由于它是一个后台线程,因此它将在应用程序退出时退出。有人可以建议 如果这是正确的方法。

 private void Form1_Load(object sender, EventArgs e)
    {
        m_dev = DASK.Register_Card(DASK.PCI_7250, 0);
        if (m_dev < 0)
        {
            MessageBox.Show("Register_Card error!");
        }
        FunctionToCall();
   }
private void FunctionToCall()
     {

        short ret;
        uint int_value;
        var thread = new Thread(() =>
            {
                while (true)
                {
                    ret = DASK.DI_ReadPort((ushort)m_dev, 0, out int_value);
                    if (ret < 0)
                    {
                        MessageBox.Show("D2K_DI_ReadPort error!");
                        return;
                    }
                    if (int_value > 0)
                   {
                       textBox2.Invoke(new UpdateText(DisplayText), Convert.ToInt32(int_value));
                    }
                    Thread.Sleep(500);
                }
            });
        thread.Start();
        thread.IsBackground = true;
    }
    private void DisplayText(int i)
    {
        textBox2.Text = i.ToString();
    }