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();
}
}
-
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– Nikita B2014年11月14日 07:55:51 +00:00Commented Nov 14, 2014 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– konijn2014年11月14日 18:19:11 +00:00Commented Nov 14, 2014 at 18:19
-
\$\begingroup\$ @konijn, if asynchronous code can possibly "go wrong", than it does not work. \$\endgroup\$Nikita B– Nikita B2014年11月18日 07:39:17 +00:00Commented Nov 18, 2014 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– Jim2014年11月18日 11:20:35 +00:00Commented Nov 18, 2014 at 11:20
1 Answer 1
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
?
-
\$\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– Jim2014年11月18日 11:26:03 +00:00Commented Nov 18, 2014 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– svick2014年11月18日 12:48:14 +00:00Commented Nov 18, 2014 at 12:48
-
\$\begingroup\$ I am talking about mocking, I mock out the compression and encryption in unit tests. \$\endgroup\$Jim– Jim2014年11月18日 12:49:37 +00:00Commented Nov 18, 2014 at 12:49