Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
处理事件时的等待方式c#_C#_Multithreading_Delay_Wait_Nonblocking - Fatal编程技术网

处理事件时的等待方式c#

处理事件时的等待方式c#,c#,multithreading,delay,wait,nonblocking,C#,Multithreading,Delay,Wait,Nonblocking,我正在写一个程序,它用串口采集数据。我尝试实现的是一个等待“循环”,在这里我可以等待几分钟,然后从串行端口获取数据。然而,在等待时,我以2Hz的速率从另一个串行端口获取数据,这是通过计时器事件完成的 我的问题是,作为一个新的c语言程序员,我不知道如何实现一个好的、可靠的等待方法。这是必需的,因为我不希望在等待下一个数据样本时执行任何操作(事件除外)。我一直在看的东西是 private async void wait(int time) { var delay =

我正在写一个程序,它用串口采集数据。我尝试实现的是一个等待“循环”,在这里我可以等待几分钟,然后从串行端口获取数据。然而,在等待时,我以2Hz的速率从另一个串行端口获取数据,这是通过计时器事件完成的

我的问题是,作为一个新的c语言程序员,我不知道如何实现一个好的、可靠的等待方法。这是必需的,因为我不希望在等待下一个数据样本时执行任何操作(事件除外)。我一直在看的东西是

    private async void wait(int time)
    {
        var delay = Task.Run(async () =>
        {
            Stopwatch sw = Stopwatch.StartNew();
            await Task.Delay(time);
            sw.Stop();
            return sw.ElapsedMilliseconds;
        });

        Debug.Write("Millisecs", delay.Result.ToString());
    }
它工作得很糟糕,因为它是非阻塞的,并且不知怎么搞砸了串行通信

    System.Threading.Thread.Sleep(120000);
它冻结了一切

  • 再创建一个线程
这似乎对我没有任何好处,因为我仍然需要冻结主线程以运行另一个线程,这使得计时器事件很难正常处理

可悲的是,写不出更好的东西,我就跟着跑

    while (ticks < 150)
    {
        Application.DoEvents();
    }

这真的是一个非常简单的方法,我不知道上次我尝试这种方法时出了什么问题

您可以将“主线程”更改为也对计时器事件执行操作。然后,如果正在运行阻塞任务,则可以添加逻辑以禁用这些计时器事件。然后,更改按钮,使其更新全局变量或向队列添加所需操作,而不是直接启动任务

使用表单计时器的非常基本的示例:

    public Action NextAction;
    public bool Running;

    private void MainForm_Load(object sender, EventArgs e)
    {
        timer1.Tick += timer1_Tick;
        timer1.Interval = 5000;
        timer1.Start();
    }

    void timer1_Tick(object sender, EventArgs e)
    {
        if (!Running && NextAction != null)
        {
            Running = true;
            NextAction();
            Running = false;
        }
    }

    void button1_Click(object sender, EventArgs e)
    {
        NextAction = () => TaskMethod();
    }

    void TaskMethod()
    {
        // do something
    }

你能分享你程序的主要部分吗?你们有什么程序控制台,窗体?目前我认为你不需要做什么。让您的程序运行…什么类型的程序?网状物WInform?命令行?你通常都有一个主线程——我通常在1秒内循环它,等待“退出程序”指令。正如其他人所提到的,你的方法可能取决于应用程序类型(控制台、WinForm、服务等)。如果这是一个具有用户界面的应用程序,那么该主UI线程永远不应该被阻止。您可以编写代码来禁用输入或控制交互,但接口本身应该始终具有响应性。话虽如此,您可能希望启动一个线程并注册一个回调,该回调将通知父线程(或其他线程)它已完成其工作或准备允许另一个线程执行另一个操作。这只是一种错误的方法,如果您等待,那么您就完了。别等了。SerialPort.DataReceived事件有助于避免等待,如果要使用async/Wait,则可以使用SerialPort.BaseStream.ReadAsync()进行读取。感谢您的评论!给了我一些思考的东西!我正在运行一个WinFormApp,其中一个窗体作为我的主UI。
    public Action NextAction;
    public bool Running;

    private void MainForm_Load(object sender, EventArgs e)
    {
        timer1.Tick += timer1_Tick;
        timer1.Interval = 5000;
        timer1.Start();
    }

    void timer1_Tick(object sender, EventArgs e)
    {
        if (!Running && NextAction != null)
        {
            Running = true;
            NextAction();
            Running = false;
        }
    }

    void button1_Click(object sender, EventArgs e)
    {
        NextAction = () => TaskMethod();
    }

    void TaskMethod()
    {
        // do something
    }