简体   繁体   English

试图使代码异步但没有阻塞我的程序快要消失了吗?

[英]Trying to make code asynchronous but without blocking my program is running away?

Writing a client / server program and previously was using calls like this: 编写客户端/服务器程序,以前使用的是这样的调用:

TcpListener.AcceptTcpClient() NetworkStream.Read() NetworkStream.Write() TcpListener.AcceptTcpClient() NetworkStream.Read() NetworkStream.Write()

TcpListener.AcceptTcpClient() is working fine because its callback function is only called after a connection is made. TcpListener.AcceptTcpClient()工作正常,因为仅在建立连接后才调用其回调函数。

However, BeginRead() is not working as well. 但是, BeginRead()不能正常工作。 For some reason it executes and continues past it even when no data is sent.. Not sure what is going on. 由于某种原因,即使没有数据发送,它也会执行并继续通过它。。不确定发生了什么。 NetworkStream.Read() was blocking just fine but this isn't.. NetworkStream.Read()阻止得很好,但是事实并非如此。

Here is the non-working thread that is created whenever a connection is established: 这是每当建立连接时都会创建的非工作线程:

private void HandleClientCommunication(object client)
{
    TcpClient tcpClient = (TcpClient)client;
    NetworkStream clientStream = tcpClient.GetStream();

    try
    {
        byte[] header = new byte[4];

        clientStream.BeginRead(header, 0, header.Length, Read, new StateData(clientStream, header)); // Runs even if no data is sent

        int dataLength = BitConverter.ToInt32(header, 0); // Continues to this, even if no packets are sent..

        byte[] data = new byte[dataLength]; // dataLength is 0 still of course because none of the code is blocking

        clientStream.BeginRead(data, 0, dataLength, Read, new StateData(clientStream, data));
    }
    catch (IOException e)
    {
        Console.WriteLine(e.InnerException.Message);
    }

    // not relevant past here
}

Here's the Read method too. 这也是Read方法。 Not sure if it's needed to figure out the problem but I'll include it regardless: 不知道是否需要找出问题,但无论如何我都会将其包括在内:

private void Read(IAsyncResult async)
{
    StateData stateData = (StateData)async.AsyncState;

    stateData.BytesRead += stateData.Stream.EndRead(async);

    if (stateData.BytesRead < stateData.Bytes.Length)
    {
        stateData.Stream.BeginRead(stateData.Bytes, 0, stateData.Bytes.Length, Read, stateData);
    }
    else
    {
        string message = Encoding.ASCII.GetString(stateData.Bytes);

        Console.WriteLine(message);
    }
}

So yeah I'm just trying to set up a client server interaction with asynchronous calls and have every "packet" include a header with the length of the data as an int and then right after that the data itself. 所以,是的,我只是想建立与异步调用的客户端服务器交互,并让每个“数据包”都包含一个标头,该标头的数据长度为整数,然后紧随其后。 Unfortunately, things seem to not be working and I'm not sure what the problem is. 不幸的是,事情似乎无法正常工作,我不确定是什么问题。

Seems like I have to include some manual form of blocking but doesn't that defeat the purpose of using asynchronous calls? 好像我必须包括某种手动形式的阻塞,但这是否违反了使用异步调用的目的? Why not just go back to regular synchronous blocking calls like Read() and AcceptTcpClient() at that point then? 那么,为什么不回到那时常规的同步阻塞调用,如Read()AcceptTcpClient()呢?

I don't think I am fully understanding things here.. 我认为我对这里的事情还不了解。

However, BeginRead() is not working as well. 但是,BeginRead()不能正常工作。 For some reason it executes and continues past it even when no data is sent.. Not sure what is going on. 由于某种原因,即使没有数据发送,它也会执行并继续通过它。。不确定发生了什么。 NetworkStream.Read() was blocking just fine but this isn't.. NetworkStream.Read()阻止得很好,但是事实并非如此。

I think you've misunderstood what BeginRead is meant to do. 我认为您误解了BeginRead的意图。 It's not meant to block - it issues an asynchronous read, executing the given callback when the read has completed. 这并不意味着块-它发出异步读取,执行指定的回调读完成。 It's meant to return immediately - so it's no wonder your header data is empty. 它的意思是立即返回-因此也就不足为奇了,您的标头数据为空。

Basically, any work which requires the data should be in the callback - not in the same method which calls BeginRead . 基本上,任何需要数据的工作都应该在回调中,而不是在调用BeginRead方法中。 Your first callback should convert the header data and then BeginRead again with a different callback to read the message data itself... although you should also bear in mind that any Read / BeginRead call may not read all the data you've asked for. 您的第一个回调应该转换头数据,然后再使用另一个回调转换BeginRead来读取消息数据本身……尽管您应该记住,任何Read / BeginRead调用都可能无法读取您要求的所有数据。 You're trying to account for this in your callback, but you're not quite there - because you're always trying to fill the buffer from the start - which will overwrite any existing data. 您正在尝试在回调中解决此问题,但您还不完全满意-因为您总是从头开始尝试填充缓冲区-这会覆盖所有现有数据。 If you know how much data you're expecting overall and your buffer is that long, you should read into the buffer starting at how many bytes you've already read. 如果您知道总体上需要多少数据并且缓冲区那么长,则应该已读取的字节数开始读入缓冲区。

Note that C# 5 will make all of this a lot simpler - but if you can't wait until then, you may well find it easier to go back to blocking calls on multiple threads (one per client). 请注意,C#5将使所有这些操作变得更加简单-但是,如果您不能等到那时,您很可能会发现回到阻塞多个线程上的调用(每个客户端一个)更容易。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 为什么异步C#套接字代码中的异常在没有堆栈跟踪的情况下终止程序? - Why do exceptions in asynchronous C# socket code terminate my program without stack trace? 不阻塞的顺序异步任务 - Sequential Asynchronous Tasks Without Blocking 限制异步请求而不阻塞 - Limiting asynchronous requests without blocking 阻塞与非阻塞异步代码 - Blocking vs Non Blocking Asynchronous code 如何保持异步程序运行? - How to keep an asynchronous program running? 异步客户端套接字 C#。 如何在不阻塞程序运行的情况下循环等待来自服务器的信息? - Asynchronous client socket c#. How can i wait in loop for informations from the server without blocking the operation of the program? 我作为Windows服务运行的C#程序阻止Windows XP进入休眠状态 - My C# program running as Windows Service is blocking Windows XP from hibernation C#如何使函数/方法等待而不阻塞程序(Unity) - C# how to Make function/Method Wait without blocking program (Unity) 我正在尝试制作我的统一程序,检测地形并更改足迹/氛围,但是我发现可以检测到它的代码未编译 - I'm trying to make my unity program, detect the terrain, and change the footsteps/ambience, but the code I've found to detect it, is not compiling 我在“ SYSTEM”帐户下运行的C#代码将如何启动需要提升而不会触发提示的程序? - How would my C# code running under “SYSTEM” account start a program which requires elevation without triggering a prompt?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM