Async / await, TAP and EAP

Viewed 1499

I'm trying to move from async socket code which is a bit messy (BeginSend/EndSend, BeginReceive/EndReceive and lots of internal 'administration') to an async TcpClient. I'm pretty new to async/await, so please bear with me...

Assume the following code (irrelevant code stripped):

public async void StartReceive()
{
    while (true)
    {
        var stream = this.MyInternalTcpClient.GetStream();
        if (stream == null) return;

        var buffer = new byte[BUFFERSIZE];
        var bytesread = await stream.ReadAsync(buffer, 0, BUFFERSIZE);
        if (bytesread == 0)
        {
            if (Closed != null)
                Closed(this, new ClosedEventArgs());
            return;
        }

        var message = this.Encoding.GetString(buffer, 0, bytesread);
        this.MyInternalStringBuilder.Append(message);
        // ... message processing here ...

        foreach (var p in parts) {
            //Raise event per message-"part"
            if (MessageReceived != null)
                MessageReceived(this, new MessageReceivedEventArgs(p));
        }
    }
}

My class has an internal stringbuilder that gets appended to each time data is received (this is because messages can be split up in more than one receive 'event'). Then, when some conditions are met, the stringbuilder (the "running buffer") is processed and the message is split into message-"parts". For each "part" an event is raised. Many instances of this class can be running in the system.

My questions are:

  1. Am I correct in assuming/understanding the MyInternalStringBuilder.Append is never called "out of order"? Each time the TcpListener receives data it will be added, "in order", to the (internal) stringbuilder? I don't need to use locks?
  2. Since this StartReceive method uses an internal ("infinite") loop and raises events I don't see the point in making the StartReceive method async, but I have to (for obviously being able to use await at all). I know I'm mixing TAP/EAP but I have to for reasons not relevant to this question. However, it feels "dirty" since "async shouldn't be void" is what I gathered so far. Maybe there's a better way to solve this (except for moving to TAP alltogether)?
4 Answers
Related