当前位置: 首页 > 知识库问答 >
问题:

如何在新线程上运行任务并立即返回调用方?

闾丘炫明
2023-03-14

在过去的几个月里,我一直在阅读C#中的异步等待以及如何正确使用它。

出于实验室练习的目的,我正在构建一个小型Tcp服务器,它应该为连接到它的客户端提供服务。该程序是一个控制台应用程序。

我使用while循环等待连接,如下所示:

while (!_isStopRequested)
{
       TcpClient client = await _tcpListener.AcceptTcpClientAsync();

       await Task.Factory.StartNew(() => ProcessClientAsync(client), TaskCreationOptions.LongRunning);
} 

所以,到目前为止,我所做的方法ProcessClientAsync被标记为异步无效,我只称之为ProcessClientAsync(客户端),调用将立即返回给调用方。然而,我在网上读到,除非是为了一个活动,否则使用它是一个糟糕的决定。所以我将定义更改为异步任务。

好的,但是没有等待,我在VisualStudio中得到一个警告“因为这个调用没有等待,所以当前方法在调用完成之前继续运行”。

一旦我使用await ProcessClientAsync(客户端),代码就不起作用了。我只能连接一个客户端,然后调用方“等待”ProcessClientSync返回。但是,该方法有一个无限循环并且不会返回,但是我需要while循环来继续处理下一个客户机。

通过谷歌搜索,我想到了这个问题:如何在C#中安全地调用异步方法而无需等待

我想问题是几乎相同的,除了当我使用wait ProcessClientAsync时,我希望它立即返回给调用者,它不这样做,我知道,因为运行第二个客户端,而第一个仍在运行,第二个客户端不连接。

所以我这样做了:

await Task.Factory.StartNew(() => ProcessClientAsync(client), TaskCreationOptions.LongRunning);

但是,由于ProcessClientAsync必须返回任务,我不确定这是否可以?

这将是一个问题。

另一个问题是:如何调用将永远运行的异步任务方法,并让调用立即返回给调用方,以便while循环可以继续,tcp侦听器可以继续接受下一个客户端?

谢谢你。

抱歉,如果是重复,或者不清楚我在问什么。

共有3个答案

年嘉禧
2023-03-14

如果我正确理解您的问题,那么以下代码应该会有所帮助:

private async void AcceptClient(TcpClient client)
{
  await Task.Factory.StartNew(() => ProcessClientAsync(client), TaskCreationOptions.LongRunning);
}

private async void Run()
{
  while (!_isStopRequested)
  {
       TcpClient client = await _tcpListener.AcceptTcpClientAsync();
       AcceptClient(client);
  }
} 
夔高寒
2023-03-14

这将启动任务并返回调用方,并避免编译器警告:

var t = Task.Factory.StartNew(() => {});
袁奇文
2023-03-14

出于实验室练习的目的,我正在构建一个小型Tcp服务器,它应该为连接到它的客户端提供服务。该程序是一个控制台应用程序。

嗯,我建议的第一件事是尝试一个更简单的练习。说真的,异步TCP服务器是您可以选择的最复杂的应用程序之一。绝大多数使用async开发人员都在开发简单两个数量级的应用程序。

相反,试着编写一个UI应用程序,从URL下载一个文件。这是学习async更现实的起点。

但是,由于ProcessClientAsync必须返回任务,我不确定这是否可以?

我建议使用任务。运行而不是任务。工厂开始新建<代码>任务。Run知道async方法,而StartNew不知道。

然而,这首先假设启动线程是正确的操作。大多数TCP/IP服务器应用程序都不受CPU的限制,因此我对多线程的使用提出了质疑。完全可以有一个完全异步的TCP/IP服务器,它只将线程池用于其async方法的延续。

另一个是:我如何调用一个将永远运行的异步任务方法,并立即将调用返回给调用方,以便同时循环可以继续,tcp监听器可以继续接受下一个客户端?

您不必等待任务返回:

Task.Run(() => ProcessClientAsync(client));

然而,编译器会在这里抱怨,因为这段代码几乎肯定是错误的。如果忽略返回的任务,则忽略该代码中的任何异常。

TCP/IP服务器应用程序中的一种常见模式是为每个连接的客户端维护一个小的状态集合。这是放置套接字对象本身和表示处理该套接字连接的任务的自然位置:

var clientState = new ClientState(client);
clientState.Task = Task.Run(() => ProcessClientAsync(client));

这些客户端状态随后存储在列表/字典中。你如何做到这一点当然取决于你自己。

 类似资料:
  • 我们开始了一个新的项目与和,并创建了一堆endpoint与QUOKUS,到目前为止一切都很好。现在我们想在其中一个endpoint中处理一些非常耗时的事情,我们期望的是,一旦用户单击一个按钮从前端发送超文本传输协议请求并点击这个特定的endpoint,我们将返回立即从后端将耗时的操作处理留在另一个线程中,然后在完成后相应地向用户发送通知电子邮件。 我知道这可以用或来完成,但是现在我们想用来完成。基

  • 我是JavaFx/并发的新手,所以我在JavaFX中阅读了并发教程,但是我仍然对JavaFX Gui中后台线程的实现有点困惑。 我试图编写一个与一些串行设备(使用JSSC-2.8)接口的小图形用户界面,并根据这些设备的响应更新图形用户界面。但是,在写入消息和设备响应之间有一个延迟,在任意的时间内使用Thread.sleep()对我来说不是一个可靠的编程方式。因此,我想使用并发包中的等待()和通知(

  • 我一直在使用线程向链接发送GET请求(一切正常)。然而,我需要它异步运行,所以我创建了一个新线程并运行了它。问题是我需要它在线程执行完毕后返回值。我用

  • 问题内容: 我有一个使用pthread的C程序。 我希望新创建的线程在创建后立即运行。 这背后的原因是我的线程具有用于设置信号处理程序的初始化代码,并且在主线程发送一些信号之前,我必须确保处理程序已就绪。 我尝试过紧随其后的尝试,但没有成功。 我怀疑这会有所不同,但是我在x86_64上运行Linux 3.6。 谢谢 问题答案: 或者,您可以使用屏障,即调用pthread_barrier_wait(

  • 我正在尝试设置一个简单的RMI服务器,该服务器绑定到注册表,供客户端获取以进行所有进一步的通信。我正在使用下面的代码: 当在我的本地机器上测试时,这工作得非常好,我能够在(本地)客户机和服务器之间建立连接。上面的main方法不会退出,直到我手动终止它,这是预期的行为。我的本地机器(Win8)运行的是Java 1.7.0_17 64位。 现在,当我在带有OpenJDK(版本1.7.0_55 64位)

  • 我试图在JavaFX中单击按钮时检索XLS文件并将其加载到TableView中。我使用Task类和ExecutorService来启动新线程。我需要reader类是可重用的,但是FileChooser没有出现。 这是我尝试编写一些并发代码。我想知道我做错了什么,我将如何改进我的代码,因为一切都是事件驱动的? 控制器类代码 阅读器类文件