1

I am developing a WCF Service on which the server would be capable to make an async call to the client request for specific bytes from a file.

Callback Contract:

public interface IControlChannelCallback
    {
        [...]

        [OperationContract(AsyncPattern = true)]
        IAsyncResult BeginGetRemoteFile(string filename, byte[] buffer, int position, int count, AsyncCallback callback, object state);

        int EndGetRemoteFile(IAsyncResult ar);
    }

Implementation:

public IAsyncResult BeginGetRemoteFile(string filename, byte[] buffer, int position, int count, AsyncCallback callback,
            object state)
        {
            var task = Task<int>.Factory.StartNew(x =>
            {
                using (var fileStream = new FileStream(filename, FileMode.Open))
                {
                    fileStream.Position = position;

                    return fileStream.Read(buffer, 0, count);
                }
            }, state);

            return task.ContinueWith(x => callback(task));
        }

        public int EndGetRemoteFile(IAsyncResult ar)
        {
            var task = (Task<int>) ar;

            return task.Result;
        }

StateObject:

public class ServiceStreamReaderStateObject
    {
        public const int BufferSize = 1024;

        public byte[] Buffer { get; private set; }

        public int TotalRead { get; set; }

        public ServiceStreamReaderStateObject()
        {
            Buffer = new byte[BufferSize];
        }
    }

Service Usage:

private void Download()
{
    var state = new ServiceStreamReaderStateObject();

    _client.Callback.BeginGetRemoteFile(@"F:\1313363989488.jpg", state.Buffer, 0,      state.Buffer.Length, RealCallback, state);
}

private void RealCallback(IAsyncResult ar)
        {
            var state = (ServiceStreamReaderStateObject) ar.AsyncState;

            var totalRead = _client.Callback.EndGetRemoteFile(ar);
        }

Everything seems to be working, when I call the EndGetRemoteFile method it returns 1024, which is how many bytes should have been read, but the problem is that the buffer encapsulated on the state object ServiceStreamReaderStateObject is empty (full of zeros).

I don't understand what I am doing wrong, following by my logic the buffer should be filled with data, what am I doing wrong here?

Bruno Klein
  • 3,217
  • 5
  • 29
  • 39

1 Answers1

0

Just a hunch: Can you remove the "private" access modifier on the Buffer property of "ServiceStreamReaderStateObject"

public class ServiceStreamReaderStateObject
{
    public const int BufferSize = 1024;

    public byte[] Buffer { get; set; }

    public int TotalRead { get; set; }

    public ServiceStreamReaderStateObject()
    {
        Buffer = new byte[BufferSize];
    }
Abhijeet Patel
  • 6,562
  • 8
  • 50
  • 93
  • Can you elaborate as to why you need position and count as parameters? Are you attempting to stream the file in chunks? – Abhijeet Patel Oct 20 '13 at 21:13
  • Yes, I want to be able to get the file in chunks, so I don't have problems with too much memory usage. – Bruno Klein Oct 20 '13 at 21:27
  • 1
    Got it. check this solution: http://stackoverflow.com/questions/14479885/wcf-streaming-large-data-500mb-1gb-on-a-self-hosted-service – Abhijeet Patel Oct 20 '13 at 21:28
  • Very interesting that WCF already supports what I am trying to do with minimal code, but the problem now is that I can't find a binding which supports, duplex AND streamed transfer. – Bruno Klein Oct 20 '13 at 23:07
  • If you are not restricted to HTTP, the NetTCP binding supports full duplex communication if you need it. Also if your service and client are both behind a firewall, "WSDualHttpBinding" might be an option as well. http://msdn.microsoft.com/en-us/library/system.servicemodel.wsdualhttpbinding.aspx – Abhijeet Patel Oct 20 '13 at 23:24
  • netTcpBinding doesn't support Duplex with Streamed transfer at the same time. Will take a look at WsDualHttpBinding. – Bruno Klein Oct 20 '13 at 23:38
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/39606/discussion-between-bruno-klein-and-abhijeet-patel) – Bruno Klein Oct 20 '13 at 23:47
  • WSDualHttpBinding works, but it doesn't have the `MaxBufferSize` property and because of this I am still getting the giant memory usage when transferring big files. Let's continue this discussion on chat. http://chat.stackoverflow.com/rooms/39606/discussion-between-bruno-klein-and-abhijeet-patel – Bruno Klein Oct 20 '13 at 23:49