diff --git a/src/ModernHttpClient.Android/ModernHttpClient.Android.csproj b/src/ModernHttpClient.Android/ModernHttpClient.Android.csproj
index 2baf578..52cbff1 100644
--- a/src/ModernHttpClient.Android/ModernHttpClient.Android.csproj
+++ b/src/ModernHttpClient.Android/ModernHttpClient.Android.csproj
@@ -65,6 +65,9 @@
ConcatenatingStream.cs
+
+ AsyncLock.cs
+
diff --git a/src/ModernHttpClient.iOS/ModernHttpClient.iOS.csproj b/src/ModernHttpClient.iOS/ModernHttpClient.iOS.csproj
index 02d95c4..0517ab3 100644
--- a/src/ModernHttpClient.iOS/ModernHttpClient.iOS.csproj
+++ b/src/ModernHttpClient.iOS/ModernHttpClient.iOS.csproj
@@ -17,7 +17,7 @@
full
false
bin\Debug
- DEBUG;
+ DEBUG; UIKIT
prompt
4
false
@@ -29,7 +29,6 @@
- full
true
bin\Release
prompt
@@ -41,6 +40,7 @@
+ UIKIT
@@ -59,5 +59,8 @@
ConcatenatingStream.cs
+
+ AsyncLock.cs
+
diff --git a/src/Shared/AsyncLock.cs b/src/Shared/AsyncLock.cs
new file mode 100644
index 0000000..e5fc709
--- /dev/null
+++ b/src/Shared/AsyncLock.cs
@@ -0,0 +1,35 @@
+using System;
+using System.Threading.Tasks;
+using System.Threading;
+
+namespace ModernHttpClient
+{
+ // Straight-up thieved from http://www.hanselman.com/blog/ComparingTwoTechniquesInNETAsynchronousCoordinationPrimitives.aspx
+ public sealed class AsyncLock
+ {
+ readonly SemaphoreSlim m_semaphore = new SemaphoreSlim(1, 1);
+ readonly Task m_releaser;
+
+ public AsyncLock()
+ {
+ m_releaser = Task.FromResult((IDisposable)new Releaser(this));
+ }
+
+ public Task LockAsync()
+ {
+ var wait = m_semaphore.WaitAsync();
+ return wait.IsCompleted ?
+ m_releaser :
+ wait.ContinueWith((_, state) => (IDisposable)state,
+ m_releaser.Result, CancellationToken.None,
+ TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default);
+ }
+
+ sealed class Releaser : IDisposable
+ {
+ readonly AsyncLock m_toRelease;
+ internal Releaser(AsyncLock toRelease) { m_toRelease = toRelease; }
+ public void Dispose() { m_toRelease.m_semaphore.Release(); }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Shared/ConcatenatingStream.cs b/src/Shared/ConcatenatingStream.cs
index 1b75ecc..fa66f74 100644
--- a/src/Shared/ConcatenatingStream.cs
+++ b/src/Shared/ConcatenatingStream.cs
@@ -12,6 +12,7 @@ namespace ModernHttpClient
{
readonly CancellationTokenSource cts = new CancellationTokenSource();
readonly Action onDispose;
+ readonly AsyncLock readLock = new AsyncLock();
long position;
bool closeStreams;
@@ -83,7 +84,15 @@ namespace ModernHttpClient
Stream stream = Current;
if (stream == null) break;
- int thisCount = await stream.ReadAsync(buffer, offset, count);
+
+ var thisCount = default(int);
+ #if UIKIT
+ using (await readLock.LockAsync()) {
+ thisCount = await stream.ReadAsync(buffer, offset, count);
+ }
+ #else
+ thisCount = await stream.ReadAsync(buffer, offset, count);
+ #endif
result += thisCount;
count -= thisCount;
@@ -127,7 +136,15 @@ namespace ModernHttpClient
Stream stream = Current;
if (stream == null) break;
- int thisCount = stream.Read(buffer, offset, count);
+
+ var thisCount = default(int);
+ #if UIKIT
+ using (readLock.LockAsync().Result) {
+ thisCount = stream.Read(buffer, offset, count);
+ }
+ #else
+ thisCount = stream.Read(buffer, offset, count);
+ #endif
result += thisCount;
count -= thisCount;