【发布时间】: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