0

I have an application which, at every tick of a timer, tries to run a backgroundWorker:

private void Timer_Tick(object sender, EventArgs e)
{
    if (!UpdateImageViewerBackgroundWorker.IsBusy)
    {
        UpdateImageViewerBackgroundWorker.RunWorkerAsync();
    }
}

When RunWorkerAsync() is called, this function executes: private void UpdateImageViewerBackgroundWorker_DoWork(object sender,

private void UpdateImageViewerBackgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
    var connected = tcp.IsConnected();

    if (connected)
    {
        var stream = tcp.NetworkStream;

        using (var memoryStream = new MemoryStream())
        {
            byte[] buffer;

            stream.CopyTo(memoryStream);
            buffer = memoryStream.ToArray();

            ....

        }
    }
    else
    {
        tcp.Connect();
    }
}

The problem is that stream.CopyTo(memoryStream); causes my backgroundWorker to deadlock, resulting in my UpdateImageViewerBackgroundWorker.IsBusy always being true.

If I add a breakpoint to the using statement and watch it, as soon as it hits that stream.CopyTo(memoryStream);, it steps over and that function is never hit again with the IsBusy always true...

It works if I define a buffer with a fixed size, and then do stream.Read(buffer, 0, BYTES_TO_READ);, but I don't want to define a buffer size as I do not know in advance how large the packet will be.

I have looked around and tried a few methods, including the one in the following post: Most efficient way of reading data from a stream - this does the same...

What am I doing wrong?

Community
  • 1
  • 1
pookie
  • 3,796
  • 6
  • 49
  • 105
  • As far as I can see, you're calling [NetworkStream.CopyTo()](http://stackoverflow.com/a/11749522/477878), not MemoryStream.CopyTo()...? – Joachim Isaksson Jan 23 '16 at 19:27
  • @JoachimIsaksson Yes, that is correct. NetworkStream has my data -- it is TCPClient.NetworkStream. I want to copy from the networkStream into the memoryStream, just as done here: http://stackoverflow.com/questions/19387979/get-length-of-data-available-in-networkstream – pookie Jan 23 '16 at 19:29
  • 1
    In case the duplicate does not answer your question please reopen. This is the same issue as far as I can tell. – usr Jan 23 '16 at 20:01
  • @usr Thanks, but it seems you are correct. Closing the TCP connectino on the server after each send does indeed fix the problem. However, is that okay - send the data, close the connection and then let the client reconnect? – pookie Jan 24 '16 at 11:58
  • @po that's correct but wasteful. Normally, you'd use a framing format such as prepending the message length before the message. Google for that. Better yes, drop TCP and use something higher level such as HTTP or WCF. – usr Jan 24 '16 at 15:17

1 Answers1

1

Probably you need using asynchronic equivalent of this method. Try use stream.CopyToAsync(memoryStream); instead of stream.CopyTo(memoryStream);. This will return a Task that can be continued on when completed, like so: await input.CopyToAsync(output).

hubot
  • 393
  • 5
  • 18