【问题标题】:How can I transfer data between a TcpListener thread and the main thread?如何在 TcpListener 线程和主线程之间传输数据?
【发布时间】:2012-06-13 06:14:32
【问题描述】:

我有一个基于 C# 的套接字通信线程。服务器中的缓冲区是 1024 字节,现在我需要一种在通信线程和主线程之间传输数据的方法。我怎样才能做到这一点?我是否需要打开一个新缓冲区,然后将数据复制到其中?或者我可以从客户端或服务器的缓冲区中获取数据吗?

private void ServerResponse()
    {
        byte[] buff = new byte[1024];
        string msg;
        int len;
        try
        {
            if (!Stream.CanRead)
            {
                return;
            }

            stopFlag = false;
            while (!stopFlag)
            {
              len = Stream.Read(buff, 0, buff.Length);
                if (len < 1                    
                  {
                    Thread.Sleep(200);
                    continue;
               }
            }
       }
 }

以上是服务器用来从客户端获取数据的函数。我的问题是我可以将这个函数获取的数据发送到主线程,或者我应该在上面的函数定义之外设置一个新的缓冲区并将数据复制到它。

【问题讨论】:

标签: c# tcp buffer tcplistener


【解决方案1】:

如果您的主线程通常被称为 UI 线程,那么本次讨论将为您提供一些想法:how to update GUI with background worker

【讨论】:

    【解决方案2】:

    取决于数据需要如何传输到主线程。如果以字节为单位,则直接调用以下代码即可。如果没有,首先将数据转换为可呈现的形式,然后调用代码:

    // Place this on the main thread's class initialization.
    private static readonly SynchronizationContext _syncContext =
        SynchronizationContext.Current;
    
    // Then your worked thread will be like this:
    if (len < 1)                  
    {
        Thread.Sleep(200);
        continue;
    }
    else
    {
        _syncContext.Post(o => MainThreadClass.ReceiveData((byte[])buff), buff);
    }
    

    【讨论】:

      【解决方案3】:

      您需要将接收到的消息写入主线程可访问的缓冲区。您可以通过为每个接收到的消息创建一个新缓冲区(一个字节数组)并将该缓冲区添加到 ConcurrentQueue<> 来做到这一点,这对于多线程读取器/写入器场景很有用。这样,您的侦听线程会将收到的消息写入队列,而您的主线程可以以线程安全的方式从同一队列中读取消息。

      根据您的用例,您可能能够构建一个更有意义的对象(例如请求对象)并将其传递给主线程而不是传递字节。

      编辑:基于评论

      假设您在公共范围内定义了 ConcurrentQueue&lt;byte[]&gt;

      public ConcurrentQueue<byte[]> ReceivedMsgs = new ConcurrentQueue<byte[]>();
      

      您可以在侦听器线程中执行类似的操作(在将消息字节读入buff 之后):

      var msg = new byte[len];
      Buffer.BlockCopy(buff, 0, msg, 0, len);
      this.ReceivedMsgs.Enqueue(msg);
      

      然后在主线程中,你可以将消息出列:

      byte[] msg;
      if (server.ReceivedMsgs.TryDequeue(out msg))
      {
          //use msg
      }
      

      【讨论】:

      • 如你所说,新的缓冲区与服务器已有的缓冲区不同,我应该创建一个主线程可访问的可读缓冲区和可写缓冲区,并将所有这些缓冲区(包括缓冲区该服务器已经拥有)到 ConsurrentQueue 中。我说的对吗?
      猜你喜欢
      • 2016-11-27
      • 2022-11-04
      • 2019-11-17
      • 1970-01-01
      • 1970-01-01
      • 2018-04-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多