【问题标题】:Is this incorrect way to implement asynchronous method这是实现异步方法的不正确方法吗
【发布时间】:2014-12-31 00:23:23
【问题描述】:

我在局域网应用程序中工作,此应用程序将接收来自许多客户端的连接
在许多情况下,我必须确保我尝试与之通信的客户端在向其发送任何数据之前已经连接,因此我创建了当前连接的客户端列表,以及一种连续发送“测试包”的方法,如关注
我将主 UI 线程与其他线程分开,稍后我将参考它
我创建了用于管理通信过程的公共类

public class Listner
{
  static TcpListener Listnerobj;
  static List<Client> Online;
  public static int port;
  public static void BeginListening()
   {
      Online = new Online(50);
      Listnerobj= new TcpListener(System.Net.IPAddress.Any, port);
      Listnerobj.Start();
      System.Threading.Thread PingerH = new System.Threading.Thread(new System.Threading.ThreadStart(PingX));
   }
}

我再次创建了线程 PingerH 来分离主 UI 线程和通信进程

private static async void PingX()
{
    while(_ping)
    {
        await PingAll();
        await CheckWhoAreDisConnected();
        System.Threading.Thread.Sleep(1000);
    }
}

方法PingAll遍历所有在线列表项并发送测试包
客户端将重放“只是回显”测试数据包,并且 LastPing 字段将被更新
CheckWhoAreDisConnected 方法检查客户端类中的 LastPing 字段
如果 DateTime.Now 和 LastPing 的减法超过 200 秒,则
该客户端已断开连接,因此 CheckWhoAreDisConnected 方法会将其从在线列表中删除
我创建了两个线程,其中一个检查网络流中的可用数据
另一个检查来自新客户端的挂起尝试 if(Listnerobj.Pending())
这是与多线程并行实现异步模式的不正确方法吗?
一般来说,应用程序逻辑是好是坏?
我是不是搞错了?

【问题讨论】:

  • 对于代码审查,请在此处发布您的问题:codereview.stackexchange.com
  • 谢谢,我不知道有代码审查部分,但是将异步与多线程混合起来怎么样?
  • 这是一个普遍的问题,不是问题。转到codereview.stackexchange.com,你会得到答案:-)

标签: c# multithreading sockets asynchronous


【解决方案1】:

如果您正确实现了异步方法,则无需在单独的线程中运行它。将返回类型 Task 设为 void 返回异步方法会吞下所有异常,并且通常仅为事件处理程序保留。而不是Thread.Sleep 使用await Task.Delay。前者阻塞线程,后者异步等待而不阻塞线程。有关最佳做法,请参阅 this article

private static async Task PingX()
{
    while(_ping)
    {
        await PingAll();
        await CheckWhoAreDisConnected();
        await Task.Delay(1000);
    }
}

我还将更改我的 BeginListening 方法以返回 Taskawait PingX()

public static Task BeginListening()
{
   Online = new Online(50);
   Listnerobj= new TcpListener(System.Net.IPAddress.Any, port);
   Listnerobj.Start();
   await PingX();
 }

【讨论】:

  • 谢谢Mr.Ned,但是单独线程的目的是主线程通过从这些方法接收数据并在主UI中查看它来做很多工作,谢谢您的指导关于如何正确使用任务,请告诉我如果我继续使用这种“异步多线程”方式是否会产生“性能开销”
  • 使用额外线程确实会使用1MB的线程本地存储,您可以使用await Task.Run(async () =&gt; await PingX())在线程池线程上运行代码,不会创建额外线程。
  • 即使这些方法使用了无限循环?如您所见,此方法使用无限循环,因为该作业应在应用程序运行时一次又一次地重复
  • while 循环只会在到达await 语句之前运行,然后它将被挂起,直到等待的语句完成。这将释放当前线程来做其他工作。但是如果你想要一个专用线程,你可以使用TaskFactory.StartNewTaskCreationOptions.LongRunning
猜你喜欢
  • 2014-12-17
  • 2012-11-11
  • 2019-09-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-23
  • 2015-05-31
  • 1970-01-01
相关资源
最近更新 更多