changeset 7:4b78cc5f116b

Fixes and improvements (some untested)
author Ivo Smits <Ivo@UCIS.nl>
date Sun, 13 Jan 2013 18:44:17 +0100
parents 5ce7a138fdba
children 9525fb2d14ec
files Database.cs Net/HTTP.cs Net/TCPStream.cs ThreadPool.cs UTF8NoPreamble.cs Util/AsyncResultBase.cs Util/QueuedPacketStream.cs Windows/ServiceManager.cs
diffstat 8 files changed, 161 insertions(+), 213 deletions(-) [+]
line wrap: on
line diff
--- a/Database.cs	Tue Jan 08 16:38:37 2013 +0100
+++ b/Database.cs	Sun Jan 13 18:44:17 2013 +0100
@@ -1,8 +1,7 @@
 using System;
-using System.Reflection;
+using System.Collections.Generic;
 using System.Data;
-using System.Data.Common;
-using System.Collections.Generic;
+using System.Reflection;
 
 namespace UCIS {
 	public class Database {
@@ -17,107 +16,103 @@
 		public string ConnectionString { get; set; }
 
 		public virtual IDbConnection GetConnection() {
-			lock (_ConnectionConstructor) {
-				IDbConnection conn = (IDbConnection)_ConnectionConstructor.Invoke(null);
-				conn.ConnectionString = ConnectionString;
-				conn.Open();
-				return conn;
+			IDbConnection conn = (IDbConnection)_ConnectionConstructor.Invoke(null);
+			conn.ConnectionString = ConnectionString;
+			conn.Open();
+			return conn;
+		}
+
+		private IDbCommand PrepareQuery(IDbConnection Connection, string Query, params object[] Parameters) {
+			IDbCommand Command = Connection.CreateCommand();
+			Command.CommandType = CommandType.Text;
+			Command.CommandText = Query;
+			Command.Parameters.Clear();
+			int ParameterI = 0;
+			foreach (object Parameter in Parameters) {
+				IDbDataParameter DBParameter = Command.CreateParameter();
+				DBParameter.Direction = ParameterDirection.Input;
+				DBParameter.ParameterName = "?" + ParameterI.ToString();
+				DBParameter.Value = Parameter;
+				Command.Parameters.Add(DBParameter);
+				ParameterI++;
 			}
+			if (ParameterI > 0) Command.Prepare();
+			return Command;
 		}
 
 		public IDbCommand PrepareQuery(string Query, params object[] Parameters) {
-			int ParameterI = 0;
 			IDbConnection Connection = GetConnection();
 			try {
-				IDbCommand Command = Connection.CreateCommand();
-				Command.CommandType = CommandType.Text;
-				Command.CommandText = Query;
-				Command.Parameters.Clear();
-				foreach (object Parameter in Parameters) {
-					IDbDataParameter DBParameter = Command.CreateParameter();
-					DBParameter.Direction = ParameterDirection.Input;
-					DBParameter.ParameterName = "?" + ParameterI.ToString();
-					DBParameter.Value = Parameter;
-					Command.Parameters.Add(DBParameter);
-					ParameterI++;
-				}
-				if (ParameterI > 0) Command.Prepare();
-				return Command;
-			} catch (Exception ex) {
+				return PrepareQuery(Connection, Query, Parameters);
+			} catch (Exception) {
 				Connection.Close();
-				throw ex;
+				throw;
 			}
 		}
 
 		public int NonQuery(string QueryString, params object[] Parameters) {
-			IDbCommand Command = PrepareQuery(QueryString, Parameters);
-			try {
-				return Command.ExecuteNonQuery();
-			} finally {
-				Command.Connection.Close();
+			using (IDbConnection connection = GetConnection()) {
+				using (IDbCommand command = PrepareQuery(connection, QueryString, Parameters)) {
+					return command.ExecuteNonQuery();
+				}
 			}
 		}
 
 		public object FetchField(string QueryString, params object[] Parameters) {
-			IDbCommand Command = PrepareQuery(QueryString, Parameters);
-			try {
-				return Command.ExecuteScalar();
-			} finally {
-				Command.Connection.Close();
+			using (IDbConnection connection = GetConnection()) {
+				using (IDbCommand command = PrepareQuery(connection, QueryString, Parameters)) {
+					return command.ExecuteScalar();
+				}
 			}
 		}
 		public object[] FetchRow(string QueryString, params object[] Parameters) {
-			IDbCommand Command = PrepareQuery(QueryString, Parameters);
-			try {
-				IDataReader Reader = Command.ExecuteReader();
-				try {
-					if (!Reader.Read()) return null;
-					object[] Result = new object[Reader.FieldCount];
-					Reader.GetValues(Result);
-					return Result;
-				} finally {
-					Reader.Close();
+			using (IDbConnection connection = GetConnection()) {
+				using (IDbCommand command = PrepareQuery(connection, QueryString, Parameters)) {
+					using (IDataReader Reader = command.ExecuteReader()) {
+						if (!Reader.Read()) return null;
+						object[] Result = new object[Reader.FieldCount];
+						Reader.GetValues(Result);
+						return Result;
+					}
 				}
-			} finally {
-				Command.Connection.Close();
 			}
 		}
 		public object[][] FetchRows(string QueryString, params object[] Parameters) {
-			IDbCommand Command = PrepareQuery(QueryString, Parameters);
-			try {
-				IDataReader Reader = Command.ExecuteReader();
-				try {
-					List<object[]> Result = new List<object[]>();
-					while (Reader.Read()) {
-						object[] ResultArray = new object[Reader.FieldCount];
-						Reader.GetValues(ResultArray);
-						Result.Add(ResultArray);
+			using (IDbConnection connection = GetConnection()) {
+				using (IDbCommand command = PrepareQuery(connection, QueryString, Parameters)) {
+					using (IDataReader Reader = command.ExecuteReader()) {
+						List<object[]> Result = new List<object[]>();
+						while (Reader.Read()) {
+							object[] ResultArray = new object[Reader.FieldCount];
+							Reader.GetValues(ResultArray);
+							Result.Add(ResultArray);
+						}
+						return Result.ToArray();
 					}
-					return Result.ToArray();
-				} finally {
-					Reader.Close();
 				}
-			} finally {
-				Command.Connection.Close();
 			}
 		}
 		public void ForEachRow(Action<Object[]> f, string QueryString, params object[] Parameters) {
-			IDbCommand Command = PrepareQuery(QueryString, Parameters);
-			try {
-				IDataReader Reader = Command.ExecuteReader();
-				try {
-					while (Reader.Read()) {
-						object[] ResultArray = new object[Reader.FieldCount];
-						Reader.GetValues(ResultArray);
-						f(ResultArray);
+			using (IDbConnection connection = GetConnection()) {
+				using (IDbCommand command = PrepareQuery(connection, QueryString, Parameters)) {
+					using (IDataReader Reader = command.ExecuteReader()) {
+						while (Reader.Read()) {
+							object[] ResultArray = new object[Reader.FieldCount];
+							Reader.GetValues(ResultArray);
+							f(ResultArray);
+						}
 					}
-				} finally {
-					Reader.Close();
 				}
-			} finally {
-				Command.Connection.Close();
 			}
-
+		}
+		public void ForEachRow(Action<IDataRecord> callback, string query, params object[] parameters) {
+			using (IDbConnection connection = GetConnection()) {
+				using (IDbCommand command = PrepareQuery(connection, query, parameters)) {
+					using (IDataReader Reader = command.ExecuteReader()) {
+						while (Reader.Read()) callback(Reader);
+					}
+				}
+			}
 		}
 
 		/*public DBReader GetReader(string QueryString, params object[] Parameters) {
--- a/Net/HTTP.cs	Tue Jan 08 16:38:37 2013 +0100
+++ b/Net/HTTP.cs	Sun Jan 13 18:44:17 2013 +0100
@@ -171,9 +171,11 @@
 			return;
 
 SendError400AndClose:
+			State = HTTPConnectionState.ProcessingRequest;
 			SendErrorAndClose(400);
 			return;
 SendError500AndClose:
+			State = HTTPConnectionState.ProcessingRequest;
 			SendErrorAndClose(500);
 			return;
 		}
@@ -288,6 +290,37 @@
 			}
 		}
 	}
+	public class HTTPStaticContent : IHTTPContentProvider {
+		public ArraySegment<Byte> ContentBuffer { get; set; }
+		public String ContentType { get; set; }
+		public HTTPStaticContent() : this(new ArraySegment<Byte>()) { }
+		public HTTPStaticContent(ArraySegment<Byte> content) : this(content, "application/octet-stream") { }
+		public HTTPStaticContent(String content, String contentType) : this(Encoding.UTF8.GetBytes(content), contentType) { }
+		public HTTPStaticContent(String contentType) : this(new ArraySegment<Byte>(), contentType) { }
+		public HTTPStaticContent(Byte[] content, String contentType) : this(new ArraySegment<Byte>(content), contentType) { }
+		public HTTPStaticContent(ArraySegment<Byte> content, String contentType) {
+			this.ContentBuffer = content;
+			this.ContentType = contentType;
+		}
+		public void SetContent(Byte[] bytes) { ContentBuffer = new ArraySegment<byte>(bytes); }
+		public void SetContent(Byte[] bytes, int offset, int count) { ContentBuffer = new ArraySegment<byte>(bytes, offset, count); }
+		public void SetContent(String content, Encoding encoding) { SetContent(encoding.GetBytes(content)); }
+		public void SetContent(String content) { SetContent(content, Encoding.UTF8); }
+		public void ServeRequest(HTTPContext context) {
+			ArraySegment<Byte> content = ContentBuffer;
+			if (content.Array == null) {
+				context.SendErrorAndClose(404);
+				return;
+			}
+			String contentType = ContentType;
+			context.SendStatus(200);
+			if (contentType != null) context.SendHeader("Content-Type", contentType);
+			context.SendHeader("Content-Length", content.Count.ToString());
+			Stream response = context.GetResponseStream();
+			response.Write(content.Array, content.Offset, content.Count);
+			response.Close();
+		}
+	}
 	public class HTTPFileProvider : IHTTPContentProvider {
 		public String FileName { get; private set; }
 		public String ContentType { get; private set; }
@@ -347,7 +380,7 @@
 						context.SendStatus(200);
 						context.SendHeader("Content-Length", fsizei.ToString());
 						String ctype = null;
-						switch (Path.GetExtension(fname).ToUpperInvariant()) {
+						switch (Path.GetExtension(fname).ToLowerInvariant()) {
 							case ".txt": ctype = "text/plain"; break;
 							case ".htm":
 							case ".html": ctype = "text/html"; break;
--- a/Net/TCPStream.cs	Tue Jan 08 16:38:37 2013 +0100
+++ b/Net/TCPStream.cs	Sun Jan 13 18:44:17 2013 +0100
@@ -3,6 +3,7 @@
 using System.Net;
 using System.Net.Sockets;
 using System.Threading;
+using UCIS.Util;
 using SysThreadPool = System.Threading.ThreadPool;
 
 namespace UCIS.Net {
@@ -76,17 +77,15 @@
 		}
 
 		public override int Read(byte[] buffer, int offset, int size) {
+			if (size < 1) return 0;
 			int Count = 0;
-
-			if (size < 1) return 0;
 			if (_HasPeekByte) {
 				buffer[offset] = _PeekByte;
 				_HasPeekByte = false;
 				Count = 1;
 				offset += 1;
-				size -= 1;
+				size = 0;
 			}
-
 			try {
 				if (size > 0) Count += Socket.Receive(buffer, offset, size, SocketFlags.None);
 			} catch (SocketException ex) {
@@ -114,34 +113,12 @@
 			return Count;
 		}
 
-		class AsyncResult : IAsyncResult {
-			public Object AsyncState { get; private set; }
-			public WaitHandle AsyncWaitHandle { get { return WaitHandle; } }
-			public Boolean CompletedSynchronously { get; private set; }
-			public Boolean IsCompleted { get; private set; }
+		class AsyncResult : AsyncResultBase {
 			public int Count { get; private set; }
-
-			private ManualResetEvent WaitHandle = new ManualResetEvent(false);
-			private AsyncCallback Callback = null;
-			private void CallCallback(Object state) {
-				if (Callback != null) Callback(this);
-			}
+			public AsyncResult(AsyncCallback callback, Object state) : base(callback, state) { }
 			public void SetCompleted(Boolean synchronously, int cnt) {
-				CompletedSynchronously = synchronously;
 				Count = cnt;
-				IsCompleted = true;
-				WaitHandle.Set();
-				if (synchronously) {
-					CallCallback(null);
-				} else {
-					if (Callback != null) SysThreadPool.QueueUserWorkItem(CallCallback);
-				}
-			}
-			public AsyncResult(AsyncCallback callback, Object state) {
-				this.Callback = callback;
-				this.AsyncState = state;
-				CompletedSynchronously = false;
-				IsCompleted = false;
+				base.SetCompleted(synchronously, null);
 			}
 		}
 		public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, object state) {
@@ -152,8 +129,6 @@
 			} else if (_HasPeekByte) {
 				buffer[offset] = _PeekByte;
 				_HasPeekByte = false;
-				offset += 1;
-				count -= 1;
 				AsyncResult ar = new AsyncResult(callback, state);
 				ar.SetCompleted(true, 1);
 				return ar;
@@ -173,8 +148,7 @@
 			if (_HasPeekByte) {
 				return _PeekByte;
 			} else {
-				int Result = 0;
-				Result = ReadByte();
+				int Result = ReadByte();
 				if (Result >= 0 && Result <= 255) {
 					_PeekByte = (byte)Result;
 					_HasPeekByte = true;
@@ -211,18 +185,11 @@
 		}
 
 		public override long Length {
-			get {
-				throw new NotSupportedException();
-			}
+			get { throw new NotSupportedException(); }
 		}
-
 		public override long Position {
-			get {
-				throw new NotSupportedException();
-			}
-			set {
-				throw new NotSupportedException();
-			}
+			get { throw new NotSupportedException(); }
+			set { throw new NotSupportedException(); }
 		}
 
 		public override long Seek(long offset, SeekOrigin origin) {
@@ -266,7 +233,7 @@
 		}
 
 		public override void Close() {
-			System.Net.Sockets.Socket s = Interlocked.Exchange(ref _Socket, null);
+			Socket s = Interlocked.Exchange(ref _Socket, null);
 			try {
 				if (s != null) {
 					try {
--- a/ThreadPool.cs	Tue Jan 08 16:38:37 2013 +0100
+++ b/ThreadPool.cs	Sun Jan 13 18:44:17 2013 +0100
@@ -1,6 +1,7 @@
 using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
 using System.Threading;
-using System.Collections.Generic;
 
 namespace UCIS {
 	public class ThreadPool {
@@ -49,7 +50,7 @@
 		}
 
 		private List<ThreadInfo> pThreads = new List<ThreadInfo>();
-		private List<ThreadInfo> pBusyThreads = new List<ThreadInfo>();
+		private int pBusyThreads = 0;
 		private Queue<ThreadInfo> pIdleThreads = new Queue<ThreadInfo>();
 		private int pThreadsMax;
 		private int pThreadsMinIdle;
@@ -58,16 +59,11 @@
 		public event OnExceptionEventHandler OnException;
 		public delegate void OnExceptionEventHandler(ThreadPool sender, ExceptionEventArgs e);
 
-		public System.Collections.ObjectModel.ReadOnlyCollection<ThreadInfo> Threads {
-			get {
-				return new System.Collections.ObjectModel.ReadOnlyCollection<ThreadInfo>(pThreads);
-			}
-		}
+		public ReadOnlyCollection<ThreadInfo> Threads { get { return pThreads.AsReadOnly(); } }
 
-		public ThreadPool() : this(250, 1, 5) { }
+		public ThreadPool() : this(250, 0, 5) { }
 
 		public ThreadPool(int MaxThreads, int MinIdle, int MaxIdle) {
-			int I = 0;
 			if (MaxThreads < 0) {
 				throw new ArgumentOutOfRangeException("ThreadsMaxIdle", "ThreadsMaxIdle must greater than 0");
 			} else if (MaxThreads < MaxIdle) {
@@ -82,20 +78,14 @@
 			pThreadsMax = MaxThreads;
 			pThreadsMinIdle = MinIdle;
 			pThreadsMaxIdle = MaxIdle;
-			for (I = 1; I <= pThreadsMinIdle; I++) {
+			for (int I = 1; I <= pThreadsMinIdle; I++) {
 				StartThread(false);
 			}
 		}
 
-		public int ThreadsIdle {
-			get { return pIdleThreads.Count; }
-		}
-		public int ThreadsBusy {
-			get { return pBusyThreads.Count; }
-		}
-		public int ThreadsAlive {
-			get { return pThreads.Count; }
-		}
+		public int ThreadsIdle { get { return pIdleThreads.Count; } }
+		public int ThreadsBusy { get { return pBusyThreads; } }
+		public int ThreadsAlive { get { return pThreads.Count; } }
 		public int ThreadsMinIdle {
 			get { return pThreadsMinIdle; }
 			set {
@@ -119,62 +109,39 @@
 		public int ThreadsMaxIdle {
 			get { return pThreadsMaxIdle; }
 			set {
-				if (pThreadsMinIdle > value) {
-					throw new ArgumentOutOfRangeException("ThreadsMaxIdle", "ThreadsMaxIdle must be greater than or equal to ThreadsMinIdle");
-				} else if (value < 0) {
-					throw new ArgumentOutOfRangeException("ThreadsMaxIdle", "ThreadsMaxIdle must greater than or equal to 0");
-				} else {
-					int I = 0;
-					int C = 0;
-					ThreadInfo T = default(ThreadInfo);
-					lock (pIdleThreads) {
-						C = pIdleThreads.Count;
-						if (value < C) {
-							for (I = value; I <= C - 1; I++) {
-								T = pIdleThreads.Dequeue();
-								T.Abort = true;
-								T.WaitHandle.Set();
-							}
-						}
+				if (pThreadsMinIdle > value) throw new ArgumentOutOfRangeException("ThreadsMaxIdle", "ThreadsMaxIdle must be greater than or equal to ThreadsMinIdle");
+				if (value < 0) throw new ArgumentOutOfRangeException("ThreadsMaxIdle", "ThreadsMaxIdle must greater than or equal to 0");
+				lock (pIdleThreads) {
+					while (value > pIdleThreads.Count) {
+						ThreadInfo T = pIdleThreads.Dequeue();
+						T.Abort = true;
+						T.WaitHandle.Set();
 					}
-					pThreadsMaxIdle = value;
 				}
+				pThreadsMaxIdle = value;
 			}
 		}
 		public int ThreadsMax {
 			get { return pThreadsMax; }
 			set {
-				if (pThreadsMaxIdle > value) {
-					throw new ArgumentOutOfRangeException("ThreadsMax", "ThreadsMax must be greater than or equal to ThreadsMaxIdle");
-				} else if (value <= 0) {
-					throw new ArgumentOutOfRangeException("ThreadsMax", "ThreadsMax must greater than 0");
-				} else {
-					pThreadsMax = value;
-				}
+				if (pThreadsMaxIdle > value) throw new ArgumentOutOfRangeException("ThreadsMax", "ThreadsMax must be greater than or equal to ThreadsMaxIdle");
+				if (value <= 0) throw new ArgumentOutOfRangeException("ThreadsMax", "ThreadsMax must greater than 0");
+				pThreadsMax = value;
 			}
 		}
 
 		public WorkItem QueueWorkItem(WaitCallback Callback, object State) {
-			WorkItem WorkItem = new WorkItem();
+			WorkItem WorkItem = new WorkItem() { Callback = Callback, State = State };
 			ThreadInfo Thread = null;
-			WorkItem.Callback = Callback;
-			WorkItem.State = State;
 			lock (pIdleThreads) {
-				while (pIdleThreads.Count > 0) {
+				while (Thread == null && pIdleThreads.Count > 0) {
 					Thread = pIdleThreads.Dequeue();
-					if (!Thread.Abort) {
-						break;
-					} else {
-						Thread = null;
-					}
+					if (Thread.Abort) Thread = null;
 				}
 			}
 			if (Thread == null)  {
-				if (pThreads.Count < pThreadsMax) {
-					Thread = StartThread(true);
-				} else {
-					throw new ThreadStateException("Thread limit exceeded");
-				}
+				if (pThreads.Count >= pThreadsMax) throw new ThreadStateException("Thread limit exceeded");
+				Thread = StartThread(true);
 			}
 			Thread.LastActive = DateTime.Now;
 			WorkItem.Thread = Thread;
@@ -235,16 +202,13 @@
 				while (true) {
 					if (Thread.WaitHandle == null) throw new ArgumentNullException("WaitHandle");
 					if (!Thread.WaitHandle.WaitOne(1000, false)) {
-						if (pBusyThreads.Count == 0) {
-							return;
-						} else {
-							continue;
-						}
-					}					
+						if (pBusyThreads <= 0) return;
+						continue;
+					}
 					if (Thread.Abort) break;
 
 					Thread.Busy = true;
-					lock (pBusyThreads) pBusyThreads.Add(Thread);
+					Interlocked.Increment(ref pBusyThreads);
 					try {
 						if (Thread.WorkItem == null) throw new ArgumentNullException("WorkItem");
 						if (Thread.WorkItem.Callback == null) throw new ArgumentNullException("WorkItem.Callback");
@@ -262,7 +226,7 @@
 							throw new Exception("Unhandled exception in work item", e.Exception);
 						}
 					} finally {
-						lock (pBusyThreads) pBusyThreads.Remove(Thread);
+						Interlocked.Decrement(ref pBusyThreads);
 					}
 					Thread.WorkItem.Thread = null;
 					Thread.WorkItem = null;
--- a/UTF8NoPreamble.cs	Tue Jan 08 16:38:37 2013 +0100
+++ b/UTF8NoPreamble.cs	Sun Jan 13 18:44:17 2013 +0100
@@ -1,5 +1,6 @@
-namespace UCIS {
-	public class UTF8NoPreamble : System.Text.UTF8Encoding {
+using System.Text;
+namespace UCIS {
+	public class UTF8NoPreamble : UTF8Encoding {
 		public UTF8NoPreamble() : base(false) { }
 	}
 }
--- a/Util/AsyncResultBase.cs	Tue Jan 08 16:38:37 2013 +0100
+++ b/Util/AsyncResultBase.cs	Sun Jan 13 18:44:17 2013 +0100
@@ -35,7 +35,13 @@
 				IsCompleted = true;
 				if (WaitEvent != null) WaitEvent.Set();
 			}
-			if (Callback != null) SysThreadPool.QueueUserWorkItem(CallCallback);
+			if (Callback != null) {
+				if (synchronously) {
+					Callback(this);
+				} else {
+					SysThreadPool.QueueUserWorkItem(CallCallback);
+				}
+			}
 		}
 
 		protected void ThrowError() {
--- a/Util/QueuedPacketStream.cs	Tue Jan 08 16:38:37 2013 +0100
+++ b/Util/QueuedPacketStream.cs	Sun Jan 13 18:44:17 2013 +0100
@@ -104,43 +104,26 @@
 			return ret;
 		}
 
-		class AsyncResult : IAsyncResult {
-			public Object AsyncState { get; private set; }
-			public WaitHandle AsyncWaitHandle { get { return WaitHandle; } }
-			public Boolean CompletedSynchronously { get; private set; }
-			public Boolean IsCompleted { get; private set; }
+		class AsyncResult : AsyncResultBase {
 			public Boolean IsReadPacket { get; private set; }
-
 			public Byte[] Buffer = null;
 			public int BufferOffset = 0;
 			public int BufferLength = 0;
 
-			private ManualResetEvent WaitHandle = new ManualResetEvent(false);
-			private AsyncCallback Callback = null;
-			private void CallCallback(Object state) {
-				if (Callback != null) Callback(this);
+			public void SetCompleted(Boolean synchronously) {
+				base.SetCompleted(synchronously, null);
 			}
-			public void SetCompleted(Boolean synchronously) {
-				CompletedSynchronously = synchronously;
-				IsCompleted = true;
-				WaitHandle.Set();
-				if (Callback != null) SysThreadPool.QueueUserWorkItem(CallCallback);
-			}
-			public AsyncResult(AsyncCallback callback, Object state) {
-				this.Callback = callback;
-				this.AsyncState = state;
-				CompletedSynchronously = false;
-				IsCompleted = false;
+			public AsyncResult(AsyncCallback callback, Object state) : base(callback, state) {
 				IsReadPacket = true;
 			}
-			public AsyncResult(AsyncCallback callback, Object state, Byte[] buffer, int bufferOffset, int bufferLength)
-				: this(callback, state) {
+			public AsyncResult(AsyncCallback callback, Object state, Byte[] buffer, int bufferOffset, int bufferLength) : base(callback, state) {
 				this.Buffer = buffer;
 				this.BufferOffset = bufferOffset;
 				this.BufferLength = bufferLength;
 				IsReadPacket = false;
 			}
 		}
+
 		private IAsyncResult BeginAsyncReadOperation(AsyncResult ar) {
 			lock (ReceiveQueue) {
 				if (AsyncReceiveOperation != null) throw new InvalidOperationException("Another asynchronous operation is in progress");
--- a/Windows/ServiceManager.cs	Tue Jan 08 16:38:37 2013 +0100
+++ b/Windows/ServiceManager.cs	Sun Jan 13 18:44:17 2013 +0100
@@ -68,8 +68,7 @@
 		public string StartPassword { get { return (string)_serviceObject.GetPropertyValue("StartPassword"); } }
 
 		public void Change(string DisplayName, string PathName, string StartMode, bool DesktopInteract, string StartName, string StartPassword) {
-			UInt32 ret;
-			ret = (UInt32)_serviceObject.InvokeMethod("Change", new Object[] {
+			UInt32 ret = (UInt32)_serviceObject.InvokeMethod("Change", new Object[] {
 					DisplayName, //DisplayName
 					PathName, //PathName
 					16, //ServiceType (16 = own process)