【问题标题】:Using events on multithreading socket server在多线程套接字服务器上使用事件
【发布时间】:2017-10-18 11:11:35
【问题描述】:

我正在为一个新游戏项目制作服务器,并且我在客户端和服务器上都使用 C# (.NET Framework v4.5)。

我目前正在使用类似的东西来管理我的玩家。

new Thread(() =>
{
   connection.ListenAndSend();
}).Start();

public void ListenAndSend()
{
    while(working)
    {
        if(someThingToRead)
        {
        //Listening logic here

        //Here i call my event for dataReceived with the data i just read.
        }
        else if (queue.Count > 0)
        {
            Send(queue.Dequeue().Data); //Send data from the Queue
        }
    }

使用队列是因为我不应该从不同的线程访问流(我认为它会抛出 InvalidOperationException),所以我实现了队列以从同一个线程发送数据。

我认为这基本没问题,但我担心这些事件。

事件正在触发并且工作正常,但我还没有对多个客户端进行测试,所以......

  • 事件是否在与侦听器线程相同的线程中执行?
  • 我会遇到多个线程同时修改字段的问题吗? (例如,我在 java 方面更有经验,我记得一些关于 Syncronize 接口的事情?)
  • 现在还没有完成,但稍后可能某些事件最终会调用发送方法,因此将数据添加到发送队列(但这应该不是问题吧?)

如果重要的话,这款游戏永远不会适合大量玩家(可能在 2 到 8 人之间)。

是否有一些我没有看到的严重问题?

当我使用队列时,我认为添加数据的线程并不重要,但在执行事件代码时我的监听会停止吗? (如果它真的在同一个线程上)虽然这可能不是一个问题,但它会同时访问来自多个线程的字段吗?

更新:

我可以只使用 async/await 来完成所有这些吗?我看不出如何以这种方式制作监听循环,但如果真的可能,请在答案中展开。

另外,这个answer 说的正好相反。

更新 2:

现在我已经测试了我的代码并且我知道它可以正常工作。

正如在 cmets 中指出的那样,我本可以使用 async/await 来实现这一点,但线程要少得多,但是:

最好使用 async/await 而不是线程,请记住我的游戏服务器应该能够根据需要占用尽可能多的 cpu/内存,如果可以的话就很好(当然线程正在调用睡眠不工作时)。而且我希望我的服务器尽可能接近实时地运行。

我还想指出,我第一次开始处理我的逻辑时,游戏地图(大约 60k 对象)的序列化大约需要 600 毫秒(这将针对每个客户端)所以我最终移动了将作业序列化到套接字线程。

考虑到这一点,谁认为使用 Async/Await 而不是新线程会更好

PD:我只说我的服务器,游戏客户端确实在使用async/await与服务器通信。

【问题讨论】:

  • 您使用的是NetworkStream吗?因为你不能从多个线程访问它是不正确的——只要你没有两个线程同时读取,或者两个线程同时写入。
  • 您将ListenAndSend 方法作为后台线程执行。除非您使用msdn.microsoft.com/en-us/library/…,否则您的事件处理程序将在同一线程中执行(并将阻止进一步接收)。
  • @C.Evenhuis 是的,我正在使用 NetworkStream,我很确定我在从另一个线程调用 Write 时遇到了异常(尽管很可能另一个线程正在调用 read),但即使我可以我?
  • @Nanoc 您可以同时在一个线程上读取并在另一个线程上写入 - 只要您没有 两个线程同时读取两个线程同时写入.
  • @C.Evenhuis 我将不得不再次检查

标签: c# multithreading sockets tcpclient


【解决方案1】:

你有 2 个选项,以太锁定变量(不推荐) How to lock a variable used in multiple threads

或使用调度程序从另一个线程调用方法Using the C# Dispatcher

如果你不使用 WPF,你可以看看这个链接:how do I convert wpf dispatcher to winforms

【讨论】:

  • 没有“来自另一个线程的方法”。线程执行,它们不拥有方法。 需要调度程序来更新 UI 控件。所有支持的 .NET 版本虽然现在都支持async/await,所以不需要使用调度程序
猜你喜欢
  • 2013-03-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-08-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多