/// <summary> /// Queues a method for execution, and specifies an object containing data to be used by the method. The method executes when a thread pool thread becomes available. /// </summary> /// <param name="callBack">A <see cref="WaitCallback"/> representing the method to execute.</param> /// <param name="state">An object containing data to be used by the method.</param> /// <returns><see langword="true"/> if the method is successfully queued; <see cref="NotSupportedException"/> is thrown if the work item could not be queued.</returns> public static bool QueueUserWorkItem(WaitCallback callBack, object state) { ThreadWorker worker = GetOrCreateFreeWorker(); if (worker != null) { worker.Post(callBack, state); return(true); } //queue a work item that is not bound to a specific thread context return(pendingWorks.Enqueue(new WorkItem(callBack, state))); }
/// <summary> /// Queues a method specified by an System.Action`1 delegate for execution, and provides data to be used by the method. The method executes when a thread pool thread becomes available. /// </summary> /// <typeparam name="TState">The type of elements of state.</typeparam> /// <param name="callBack">An Action representing the method to execute.</param> /// <param name="state">An object containing data to be used by the method.</param> /// <param name="preferLocal"><see langword="true"/> to prefer queueing the work item in a queue close to the current thread; <see langword="false"/> to prefer queueing the work item to the thread pool's shared queue.</param> /// <returns><see langword="true"/> if the method is successfully queued; <see cref="NotSupportedException"/> is thrown if the work item could not be queued. </returns> public static bool QueueUserWorkItem <TState>(Action <TState> callBack, TState state, bool preferLocal) { if (preferLocal) { throw new Exception("PreferLocal:true not supported"); } ThreadWorker worker = GetOrCreateFreeWorker(); if (worker != null) { worker.Post((_) => callBack(state), null); return(true); } return(pendingWorks.Enqueue(new WorkItem((_) => callBack(state), state))); }
static internal void RunPendingWorkItems(ThreadWorker callingWorker) { lock (mlock) { //first find the first workitem that was requested to be run on this calling worker and start it for (int i = 0; i < pendingWorks.Count; i++) { //TODO: remove this workitem from queue, figured it will be removed below WorkItem work = pendingWorks[i]; //if the work must be run on this thread if (work.workerId == callingWorker.Id) { //post the job back to the callingWorker callingWorker.Post(work.callBack, work.state); } } //now run all other pending works on any available pool while (pendingWorks.Count > 0) { //get an available pool ThreadWorker pool = GetOrCreateFreeWorker(); if (pool != null) { do { WorkItem work = default; if (pendingWorks.Dequeue(ref work)) { //if the work can be run on any thread if (work.workerId < 0) { pool.Post(work.callBack, work.state); } else { continue; } } } while (false); } } } }
internal static bool QueueUserWorkItemOnSpecificWorker(int threadId, WaitCallback callBack, object state) { ThreadWorker worker = GetWorkerById(threadId); if (worker == null) { throw new Exception($"No such worker with id {threadId}"); } if (worker.IsFree) { worker.Post(callBack, state); return(true); } else { //queue a work item that is bound to a specific thread context(threadId) return(pendingWorks.Enqueue(new WorkItem((_) => callBack(state), state, threadId))); } }
public async Task <ushort> SendData(byte[] data) { try { await locker.WaitAsync(); await Task.Delay(1000); ushort _messageId = (ushort)storage.GetShort(device.Id, "message-id", 0); var ___messageId = _messageId + 1; storage.PutShort(device.Id, "message-id", (short)___messageId); i++; if (i % 8 == 0) { throw new Exception("Dummy send error"); } var m = Message.Unpack(data, new InMemoryBuffer()); if (m is BalanceMO balance) { thread.PostDelayed(() => { var balanceMT = BalanceMT.Create(ProtocolVersion.v3__WeatherExtension, DateTime.UtcNow, DateTime.UtcNow.AddDays(-12), DateTime.UtcNow.AddDays(30), 672, 1000, 328).Pack(); PacketReceived(this, new PacketReceivedEventArgs() { Payload = balanceMT[0].Payload, MessageId = (short)(10006 + ___messageId), }); }, TimeSpan.FromSeconds(15)); } if (m is MessageSentMO sent) { thread.PostDelayed(() => { var resendIndexes = new byte[resendParts]; for (int k = 0; k < resendParts; k++) { resendIndexes[k] = (byte)k; } resendParts -= 2; if (resendParts < 0) { resendParts = 2; } var ack = MessageAckMT.Create(ProtocolVersion.v3__WeatherExtension, (byte)sent.SentGroup, resendIndexes).Pack(); PacketReceived(this, new PacketReceivedEventArgs() { Payload = ack[0].Payload, MessageId = (short)(10005 + ___messageId), }); }, TimeSpan.FromSeconds(10)); } thread.Post(async() => { await Task.Delay(TimeSpan.FromSeconds(4)); PacketStatusUpdated(this, new PacketStatusUpdatedEventArgs() { MessageId = (short)_messageId, Status = MessageStatus.Transmitted, }); //await Task.Delay(TimeSpan.FromSeconds(6)); //var m = Message.Unpack(data) as ChatMessageMO; //if (m != null && m.TotalParts == 1) //{ //var p = ChatMessageMT.Create(m.Version, m.Subscriber, m.Id, m.Conversation, m.Text, m.Lat, m.Lon, m.Alt, m.ByskyToken, m.File, m.FileExtension, m.ImageQuality, m.Subject).Pack(); //PacketReceived(this, new PacketReceivedEventArgs() //{ // Payload = p[0].Payload, // MessageId = (short)(10000 + ___messageId), //}); //} }); return(_messageId); } finally { locker.Release(); } }