4
\$\begingroup\$

Assuming I have to leave the contract intact (take byte[] and return byte[]), what's the correct way to structure this asynchronous method?

Will this deadlock running in ASP.NET in a web server thread?

public async Task<byte[]> CompressAsync(byte[] buffer)
{
    using (var outStream = new MemoryStream())
    {
        using (var tinyStream = new GZipStream(outStream, CompressionMode.Compress))
        using (var stream = new MemoryStream(buffer))
        {
            await stream.CopyToAsync(tinyStream);
        }

        return outStream.ToArray();
    }            
}
\$\endgroup\$
4
  • 3
    \$\begingroup\$ I think your last question is off-topic. We review working code here, while you are kind of asking us if your code works. \$\endgroup\$ – Nikita B Nov 14 '14 at 7:55
  • 1
    \$\begingroup\$ @NikitaBrizhak Disagreed, it is very hard to test for deadlocks. All asynchronous code can possibly go wrong, that does not mean all asynchronous code is not working. \$\endgroup\$ – konijn Nov 14 '14 at 18:19
  • \$\begingroup\$ @konijn, if asynchronous code can possibly "go wrong", than it does not work. \$\endgroup\$ – Nikita B Nov 18 '14 at 7:39
  • \$\begingroup\$ The code does work. I passes several unit and integration tests. The trick is that unless async and await are used throughout the pipeline, ASP.NET can deadlock. Most library code needs to use ConfigureAwait in order to ensure it works when an ASP.NET thread waits. It's mentioned in the answer below. I agree the statement that all asynchronous code can go wrong is basically solipsist. \$\endgroup\$ – Jim Nov 18 '14 at 11:20
2
\$\begingroup\$

I don't see any reason for the inner stream. Instead, you can just WriteAsync() the whole buffer directly into the (confusingly named) tinyStream.


Your code won't deadlock if used properly (i.e. asynchronously), but it will deadlock if someone synchronously waits for it (e.g. byte[] resultBuffer = CompressAsync(inputBuffer).Result;). To make sure this doesn't happen, add .ConfigureAwait(false) after every await.

You should do this for all your "library" code, that is code that doesn't need to run in the ASP.NET request context/GUI thread.


This method doesn't use any instance state. Why isn't it static?

\$\endgroup\$
3
  • \$\begingroup\$ I almost never use static methods for anything. This method is part of a larger class that implements an interface to ensure it can be doubled in unit and integration tests. I don't really have static methods anymore as everything needs tests. \$\endgroup\$ – Jim Nov 18 '14 at 11:26
  • \$\begingroup\$ @Jim You can test static methods just as easily as instance methods. Or are you talking about the difficulty of mocking them? \$\endgroup\$ – svick Nov 18 '14 at 12:48
  • \$\begingroup\$ I am talking about mocking, I mock out the compression and encryption in unit tests. \$\endgroup\$ – Jim Nov 18 '14 at 12:49

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.