【问题标题】:How can you asynchronously call a method containing an infinite loop without blocking?如何在不阻塞的情况下异步调用包含无限循环的方法?
【发布时间】:2014-07-29 20:25:16
【问题描述】:

我一直在开发一个使用 async 和 await 关键字异步连接到服务器的客户端应用程序。我试图异步调用一个无限循环的方法,每隔几秒钟检查一次互联网连接。这是我开始连接时的初始代码。

    private async void button1_Click(object sender, EventArgs e)
    {
        if (button1.Text == "Connect")
        {
            button1.Enabled = false;
            await ConnectClient();

            await Task.Run(() => CheckForInternet());
            //Doesn't execute past this line
            button1.Enabled = true;
        }

        ...
    }

这是我的 CheckForInternet() 方法的作用

    private async Task CheckForInternet()
    {      
        while (true)
        {   //Close out of the method when done checking
            if (stopCheckingForInternet)
                return;

            //If there is internet
            if (InternetGetConnectedState())
            {
              ...
            }
            //If an internet connection was lost
            else
            {
              ...
            }
        }

    }

我希望 CheckForInternet() 方法在我调用它之后拥有自己的单独线程,并且能够不阻塞,但不需要使用 Thread 类。我尝试了使用的方法 http://blog.stephencleary.com/2013/11/taskrun-etiquette-examples-dont-use.html

换句话说,有没有办法使用这些方法异步启动一个线程,然后在线程启动后,控制权可以返回到调用它的上下文吗?

异步调用阻塞,除非完全终止,否则不会通过它。我想让线程无限期地保持运行,但也能够返回到我调用此异步方法而不是阻塞的行下面的行,并且永远不允许执行调用下面的行。

【问题讨论】:

  • Task.Factory.StartNew(() => CheckForInternet()) - 我没有在 C# 中使用新的 await 东西,但我想说如果你不想阻塞 UI 线程,那么就分拆新的无需等待即可完成任务。
  • 您的解决方案奏效了!您应该已将其发布为答案。
  • 哦,好吧,我很着急,没有阅读整个问题,所以我想我会错过一些东西。想对我的第一个问题发表评论,以防我再也回不来正确回答问题。

标签: c# asynchronous client infinite-loop blocking


【解决方案1】:

在这种情况下,您不应该使用 async/await。 “等待”将使您的方法阻塞。您应该只使用 Task.StartNew() 作为您的 CheckForInternet 方法(或其他合适的创建任务的方法)。

在 CheckForInternet 中,我认为最好在其中放置一个“Thread.Sleep()”,以避免不必要的 CPU 消耗。

创建任务会自动创建一个内部线程。

如果用于解除 I/O 阻塞,Async/await 很有意义。

【讨论】:

    【解决方案2】:

    你可以选择不awaitTask.Run返回的任务;这将使您的循环独立。

    但是,我建议您要么在 CheckForInternet 中使用顶级 try/catch,要么保存返回的 Task 并在完成时做出适当的响应。

    【讨论】:

    • 假设该方法永远不会完成,只有在程序终止时才停止,那么你有什么建议?
    • 您可以只使用顶级try/catch 并使用Task.Run 调用它。
    猜你喜欢
    • 2022-09-27
    • 2014-12-09
    • 1970-01-01
    • 2014-09-20
    • 2022-07-01
    • 2019-10-27
    • 1970-01-01
    • 1970-01-01
    • 2021-06-10
    相关资源
    最近更新 更多