diff --git a/SignalR.Client/Connection.cs b/SignalR.Client/Connection.cs
index 311d48a89f..0c91d8f0eb 100644
--- a/SignalR.Client/Connection.cs
+++ b/SignalR.Client/Connection.cs
@@ -5,7 +5,6 @@
using System.Linq;
using System.Net;
using System.Reflection;
-using System.Threading;
using System.Threading.Tasks;
using Newtonsoft.Json.Linq;
using SignalR.Client.Http;
@@ -21,8 +20,12 @@ public class Connection : IConnection
private static Version _assemblyVersion;
private IClientTransport _transport;
- private ConnectionState _state;
- private CancellationTokenSource _cancel;
+
+ // The default connection state is disconnected
+ private ConnectionState _state = ConnectionState.Disconnected;
+
+ // Used to synchornize state changes
+ private readonly object _stateLock = new object();
///
/// Occurs when the has received data from the server.
@@ -135,14 +138,6 @@ public Connection(string url, string queryString)
///
public string QueryString { get; private set; }
- public CancellationToken CancellationToken
- {
- get
- {
- return _cancel.Token;
- }
- }
-
///
/// Gets the current of the connection.
///
@@ -150,7 +145,10 @@ public ConnectionState State
{
get
{
- return _state;
+ lock (_stateLock)
+ {
+ return _state;
+ }
}
private set
{
@@ -166,18 +164,6 @@ private set
}
}
- ConnectionState IConnection.State
- {
- get
- {
- return State;
- }
- set
- {
- State = value;
- }
- }
-
///
/// Starts the .
///
@@ -209,15 +195,11 @@ public Task Start(IHttpClient httpClient)
/// A task that represents when the connection has started.
public virtual Task Start(IClientTransport transport)
{
- if (State == ConnectionState.Connected ||
- State == ConnectionState.Connecting)
+ if (!ChangeState(ConnectionState.Disconnected, ConnectionState.Connecting))
{
return TaskAsyncHelper.Empty;
}
- State = ConnectionState.Connecting;
- _cancel = new CancellationTokenSource();
-
_transport = transport;
return Negotiate(transport);
@@ -271,8 +253,29 @@ private Task Negotiate(IClientTransport transport)
private Task StartTransport(string data)
{
- return _transport.Start(this, _cancel.Token, data)
- .Then(() => State = ConnectionState.Connected);
+ return _transport.Start(this, data)
+ .Then(() =>
+ {
+ ChangeState(ConnectionState.Connecting, ConnectionState.Connected);
+ });
+ }
+
+ private bool ChangeState(ConnectionState oldState, ConnectionState newState)
+ {
+ return ((IConnection)this).ChangeState(oldState, newState);
+ }
+
+ bool IConnection.ChangeState(ConnectionState oldState, ConnectionState newState)
+ {
+ lock (_stateLock)
+ {
+ if (_state == oldState)
+ {
+ State = newState;
+ return true;
+ }
+ return false;
+ }
}
private static void VerifyProtocolVersion(string versionString)
@@ -294,14 +297,11 @@ public virtual void Stop()
try
{
// Do nothing if the connection is offline
- if (this.IsDisconnecting())
+ if (State == ConnectionState.Disconnected)
{
return;
}
- State = ConnectionState.Disconnecting;
-
- _cancel.Cancel(throwOnFirstException: false);
_transport.Stop(this);
if (Closed != null)
@@ -327,7 +327,7 @@ public Task Send(string data)
Task IConnection.Send(string data)
{
- if (this.IsDisconnecting())
+ if (State == ConnectionState.Disconnected)
{
// TODO: Update this error message
throw new InvalidOperationException("Start must be called before data can be sent");
diff --git a/SignalR.Client/ConnectionExtensions.cs b/SignalR.Client/ConnectionExtensions.cs
index 8e706878cd..50e6ed688c 100644
--- a/SignalR.Client/ConnectionExtensions.cs
+++ b/SignalR.Client/ConnectionExtensions.cs
@@ -16,18 +16,6 @@ public static T GetValue(this IConnection connection, string key)
return default(T);
}
- public static bool IsDisconnecting(this IConnection connection)
- {
- return connection.State == ConnectionState.Disconnecting ||
- connection.State == ConnectionState.Disconnected;
- }
-
- public static bool IsActive(this IConnection connection)
- {
- return connection.State == ConnectionState.Connected ||
- connection.State == ConnectionState.Connecting;
- }
-
#if !WINDOWS_PHONE && !SILVERLIGHT && !NET35
public static IObservable AsObservable(this Connection connection)
{
diff --git a/SignalR.Client/ConnectionState.cs b/SignalR.Client/ConnectionState.cs
index 73177e8fdb..99028df137 100644
--- a/SignalR.Client/ConnectionState.cs
+++ b/SignalR.Client/ConnectionState.cs
@@ -5,7 +5,6 @@ public enum ConnectionState
Connecting,
Connected,
Reconnecting,
- Disconnecting,
Disconnected
}
}
diff --git a/SignalR.Client/IConnection.cs b/SignalR.Client/IConnection.cs
index 6804e59eac..2f1e0a8d29 100644
--- a/SignalR.Client/IConnection.cs
+++ b/SignalR.Client/IConnection.cs
@@ -16,7 +16,9 @@ public interface IConnection
string ConnectionId { get; }
string Url { get; }
string QueryString { get; }
- ConnectionState State { get; set; }
+ ConnectionState State { get; }
+
+ bool ChangeState(ConnectionState oldState, ConnectionState newState);
ICredentials Credentials { get; set; }
CookieContainer CookieContainer { get; set; }
diff --git a/SignalR.Client/Transports/AutoTransport.cs b/SignalR.Client/Transports/AutoTransport.cs
index 87f4452749..2986d9d552 100644
--- a/SignalR.Client/Transports/AutoTransport.cs
+++ b/SignalR.Client/Transports/AutoTransport.cs
@@ -26,22 +26,22 @@ public Task Negotiate(IConnection connection)
return HttpBasedTransport.GetNegotiationResponse(_httpClient, connection);
}
- public Task Start(IConnection connection, CancellationToken cancellationToken, string data)
+ public Task Start(IConnection connection, string data)
{
var tcs = new TaskCompletionSource