/// <summary> /// 添加任务(有返回值) /// </summary> /// <param name="item">传入任务参数</param> /// <param name="func">需要执行的任务,返回值为任务完成后需要接受的值</param> /// <param name="taskFinishAction">任务结束后需要返回的结果,如果执行成功,其中T2的值为func委托的响应值</param> public void Add(T item, Func <T, CancellationTokenSource, T2> func, Action <bool, T2, Exception> taskFinishAction = null) { Guid guid = Guid.NewGuid(); AwaitList.Add(guid, new TaskJobParam <T>(guid, item)); StartProcessForWait(func, taskFinishAction); }
/// <summary> /// Applies the specified value. /// </summary> /// <param name="value">The value.</param> private void applyString(byte[] value) { if (operations.Count == 0) { receivedData.Enqueue(value); return; } object nextOp = operations.Peek(); if (nextOp is AwaitString && !((AwaitString)nextOp).readSize) { AwaitString op = (AwaitString)nextOp; int size = Convert.ToInt32(Encoding.ASCII.GetString(value)); op.readSize = true; op.size = size; op.data = new byte[] {}; if (op.size < 0) { operations.Pop(); applyString(null); } } else if (nextOp is AwaitList && !((AwaitList)nextOp).readLength) { AwaitList op = (AwaitList)nextOp; int length = Convert.ToInt32(Encoding.ASCII.GetString(value)); op.readLength = true; op.length = length; if (op.length < 0) { operations.Pop(); applyString(null); } op.data = new object[length]; } else { if (!applyToList(value)) { receivedData.Enqueue(value); operations.Push(new AwaitCrLf()); } } }
/// <summary> /// Applies to list. /// </summary> /// <param name="value">The value.</param> /// <returns><c>true</c> if the object was applied to a list, <c>false</c> if another application should be attempted.</returns> private bool applyToList(object value) { object nextOp = operations.Peek(); if (!(nextOp is AwaitList)) { return(false); } AwaitList op = (AwaitList)nextOp; if (op.objectsRead >= op.length) { return(false); } else { op.data[op.objectsRead++] = value; return(true); } }
/// <summary> /// 开始执行等待进行的任务 /// </summary> private void StartProcessForWait(Func <T, CancellationTokenSource, T2> func, Action <bool, T2, Exception> taskFinishAction) { if (AwaitList.Count > 0 && IsStartNewProcess) { TaskJobParam <T> taskJobParam = base.GetFirstJob <TaskJobParam <T> >(AwaitList); if (taskJobParam != null) { if (AwaitList.ContainsKey(taskJobParam.Id)) { AwaitList.Remove(taskJobParam.Id); } StartNewProcess(taskJobParam, func, taskFinishAction); } } else { if (_duration > 0) { Thread.Sleep(_duration); } } }
/// <summary> /// Updates the internal states based on the latest bytes read. /// </summary> /// <param name="bytesRead">The number of bytes read.</param> /// <exception cref="System.NotImplementedException"> /// Operation not implemented for + encoding.GetString(buffer, bufferIndex, 1) /// or /// Don't know what to do. /// </exception> /// <exception cref="System.InvalidOperationException"> /// Protocol Violation. Expected CR-LF. /// or /// Protocol Violation. Expected CR. /// or /// Protocol Violation. Expected LF. /// </exception> public void update(int bytesRead) { int bufferIndex = 0; while (bufferIndex < buffer.Length && bufferIndex < bytesRead) { if (operations.Count == 0) { operations.Push(new AwaitCommand()); } object nextOp = operations.Peek(); if (nextOp is AwaitCommand) { switch (buffer[bufferIndex]) { case PLUS: operations.Pop(); operations.Push(new AwaitSimpleString()); ++bufferIndex; continue; case DOLLAR: operations.Pop(); operations.Push(new AwaitString { readSize = false }); operations.Push(new AwaitSimpleString()); ++bufferIndex; continue; case COLON: operations.Pop(); operations.Push(new AwaitInt()); ++bufferIndex; continue; case ASTERISK: operations.Pop(); operations.Push(new AwaitList { readLength = false }); operations.Push(new AwaitSimpleString()); ++bufferIndex; continue; case MINUS: operations.Pop(); operations.Push(new AwaitError()); operations.Push(new AwaitSimpleString()); ++bufferIndex; continue; default: throw new NotImplementedException("Operation not implemented for " + encoding.GetString(buffer, bufferIndex, 1)); } } else if (nextOp is AwaitCrLf) { AwaitCrLf op = (AwaitCrLf)nextOp; int availableLength = buffer.Length - bufferIndex; if (availableLength < 1) { continue; } if (!op.cr) { if (availableLength >= 2) { if (buffer[bufferIndex] == CR && buffer[bufferIndex + 1] == LF) { operations.Pop(); bufferIndex += 2; } else { throw new InvalidOperationException("Protocol Violation. Expected CR-LF."); } } else { if (buffer[bufferIndex] == CR) { op.cr = true; ++bufferIndex; } else { throw new InvalidOperationException("Protocol Violation. Expected CR."); } } } else { if (buffer[bufferIndex] == LF) { operations.Pop(); ++bufferIndex; } else { throw new InvalidOperationException("Protocol Violation. Expected LF."); } } } else if (nextOp is AwaitSimpleString) { AwaitSimpleString op = (AwaitSimpleString)nextOp; IEnumerable <byte> partialBuffer = buffer.Skip(bufferIndex).Take(bytesRead - bufferIndex); byte[] potential = op.data == null?partialBuffer.ToArray() : op.data.Concat(partialBuffer).ToArray(); int indexCrLf = potential.indexOf(CrLf); if (indexCrLf == -1) { op.data = potential; bufferIndex = buffer.Length; } else { byte[] stringData = potential.Take(indexCrLf).ToArray(); operations.Pop(); if (operations.Count > 0 && operations.Peek() is AwaitError) { operations.Pop(); apply(new RedisErrorException(encoding.GetString(stringData))); } else { applyString(stringData); } bufferIndex += indexCrLf + CrLf.Length - (op.data == null ? 0 : op.data.Length); } } else if (nextOp is AwaitInt) { AwaitInt op = (AwaitInt)nextOp; IEnumerable <byte> partialBuffer = buffer.Skip(bufferIndex).Take(bytesRead - bufferIndex); byte[] potential = op.data == null?partialBuffer.ToArray() : op.data.Concat(partialBuffer).ToArray(); int indexCrLf = potential.indexOf(CrLf); if (indexCrLf == -1) { op.data = potential; bufferIndex = buffer.Length; } else { byte[] stringData = potential.Take(indexCrLf).ToArray(); string valueLiteral = _encoding.GetString(stringData); operations.Pop(); long value; if (long.TryParse(valueLiteral, out value)) { apply(value); } else { apply(new Exception(string.Format("Failed to parse {0} as an integer", valueLiteral))); } bufferIndex += indexCrLf + CrLf.Length - (op.data == null ? 0 : op.data.Length); } } else if (nextOp is AwaitString) { AwaitString op = (AwaitString)nextOp; int currentSize = op.data.Length; int availableLength = buffer.Length - bufferIndex; if (currentSize + availableLength >= op.size) { int count = op.size - op.data.Length; byte[] stringData = op.data.Concat(buffer.Skip(bufferIndex).Take(count)).ToArray(); operations.Pop(); applyString(stringData); bufferIndex = bufferIndex + count; operations.Push(new AwaitCrLf()); continue; } else { op.data = op.data.Concat(buffer.Skip(bufferIndex).Take(availableLength)).ToArray(); bufferIndex = bufferIndex + availableLength; } } else if (nextOp is AwaitList) { AwaitList op = (AwaitList)nextOp; if (op.objectsRead < op.length) { operations.Push(new AwaitCommand()); } } else { throw new NotImplementedException("Don't know what to do."); } nextOp = operations.Count > 0 ? operations.Peek() : null; while (nextOp is AwaitList && ((AwaitList)nextOp).objectsRead >= ((AwaitList)nextOp).length) { operations.Pop(); apply(((AwaitList)nextOp).data); nextOp = operations.Count > 0 ? operations.Peek() : null; } if (operations.Count == 0) { // Opportunity here to convert from "internal" state to "external" state. Queue receivedObject = new Queue(receivedData.Count); while (receivedData.Count > 0) { receivedObject.Enqueue(receivedData.Dequeue()); } _onObjectReceived(new ObjectReceivedEventArgs(receivedObject)); } } }