/// <summary> /// Starts reading data from an incoming stream. /// The <paramref name="readCallback"/> will be executed several times until the stream closes or <see cref="ReadStop"/> method is called. /// </summary> /// <param name="allocCallback">Allocation callback.</param> /// <param name="readCallback">Read callback.</param> /// <param name="state">State to be passed to the callbacks.</param> public void ReadStart(AllocCallbackDelegate allocCallback, ReadCallbackDelegate readCallback, object state = null) { this.EnsureCallingThread(); if (this._ReadVitality.IsAllocated) { throw new InvalidOperationException("ReadStop must be called before ReadStart may be called again."); } try { this._ReadVitality = GCHandle.Alloc(this, GCHandleType.Normal); this._UserAllocCallback = allocCallback; this._UserReadCallback = readCallback; this._UserReadState = state; Libuv.EnsureSuccess(Libuv.uv_read_start(this, _UvAllocCallback, _UvReadCallback)); } catch (Exception) { this._UserAllocCallback = null; this._UserReadCallback = null; this._UserReadState = null; if (this._ReadVitality.IsAllocated) { this._ReadVitality.Free(); } throw; } }