public TItem Dequeue(CancellationToken cancellationToken = default) { while (!cancellationToken.IsCancellationRequested) { lock (_syncRoot) { if (_items.Count > 0) { var item = _items.First.Value; _items.RemoveFirst(); return(item); } if (_items.Count == 0) { _gate?.Reset(); } } _gate?.Wait(cancellationToken); } throw new OperationCanceledException(); }
// Validates init, set, reset state transitions. private static void RunManualResetEventSlimTest0_StateTrans(bool init) { ManualResetEventSlim ev = new ManualResetEventSlim(init); if (ev.IsSet != init) { Debug.WriteLine("* RunManualResetEventSlimTest0_StateTrans(init={0})", init); Assert.True(false, string.Format(" > FAILED. expected IsSet=={0}, but it's {1}", init, ev.IsSet)); } for (int i = 0; i < 50; i++) { ev.Set(); if (!ev.IsSet) { Debug.WriteLine("* RunManualResetEventSlimTest0_StateTrans(init={0})", init); Assert.True(false, string.Format(" > FAILED. expected IsSet, but it's false")); } ev.Reset(); if (ev.IsSet) { Debug.WriteLine("* RunManualResetEventSlimTest0_StateTrans(init={0})", init); Assert.True(false, string.Format(" > FAILED. expected !IsSet, but it's true")); } } }
private unsafe void Receive(byte[] data) { // Schedule the processing to happen on the queue. Out of order // messages cause checksum errors! _queue.DispatchAsync(() => { _receivedBytesPending += (uint)data.Length; WriteLog.To.Sync.V(Tag, $"<<< received {data.Length} bytes [now {_receivedBytesPending} pending]"); var socket = _socket; _c4Queue.DispatchAsync(() => { // Guard against closure / disposal if (!_closed) { Native.c4socket_received(socket, data); WriteLog.To.Sync.V(Tag, "c4Socket received."); if (_receivedBytesPending >= MaxReceivedBytesPending) { WriteLog.To.Sync.V(Tag, "Too much pending data, throttling Receive..."); _receivePause?.Reset(); } } }); }); }
// Validates init, set, reset state transitions. private static void RunManualResetEventSlimTest0_StateTrans(bool init) { ManualResetEventSlim ev = new ManualResetEventSlim(init); Assert.Equal(init, ev.IsSet); for (int i = 0; i < 50; i++) { ev.Set(); Assert.True(ev.IsSet); ev.Reset(); Assert.False(ev.IsSet); } }
/// <summary> /// Disconnects from the server. The server is actively notified about disconnection. /// </summary> public void Disconnect() { if (_channel != null && HasSession) { if (_keepSessionAliveTimer != null) { _keepSessionAliveTimer.Stop(); _keepSessionAliveTimer.Dispose(); _keepSessionAliveTimer = null; } byte[] sharedSecret = MessageEncryption ? _sessionId.ToByteArray() : null; var goodbyeMessage = new GoodbyeMessage() { SessionId = _sessionId }; var wireMessage = MessageEncryptionManager.CreateWireMessage( messageType: "goodbye", serializer: Serializer, serializedMessage: Serializer.Serialize(goodbyeMessage), keyPair: _keyPair, sharedSecret: sharedSecret); byte[] rawData = Serializer.Serialize(wireMessage); _goodbyeCompletedWaitHandle.Reset(); _channel.RawMessageTransport.SendMessage(rawData); _goodbyeCompletedWaitHandle.Wait(10000); } _channel?.Disconnect(); _handshakeCompletedWaitHandle?.Reset(); _authenticationCompletedWaitHandle?.Reset(); Identity = null; }
public static void RunManualResetEventSlimTest5_Dispose_Negative() { ManualResetEventSlim mres = new ManualResetEventSlim(false); mres.Dispose(); Assert.Throws<ObjectDisposedException>(() => mres.Reset()); // Failure Case: The object has been disposed, should throw ObjectDisposedException. Assert.Throws<ObjectDisposedException>(() => mres.Wait(0)); // Failure Case: The object has been disposed, should throw ObjectDisposedException. Assert.Throws<ObjectDisposedException>( () => { WaitHandle handle = mres.WaitHandle; }); // Failure Case: The object has been disposed, should throw ObjectDisposedException. mres = new ManualResetEventSlim(false); ManualResetEvent mre = (ManualResetEvent)mres.WaitHandle; mres.Dispose(); Assert.Throws<ObjectDisposedException>(() => mre.WaitOne(0)); // Failure Case: The underlying event object has been disposed, should throw ObjectDisposedException. }
public void WaitForWorkers() { endHandle.Wait(); endHandle.Reset(); }
/// <summary> /// Returns an enumerable which provides the data to stream to the algorithm /// </summary> public override IEnumerable <TimeSlice> StreamData(CancellationToken cancellationToken) { PostInitialize(); var shouldSendExtraEmptyPacket = false; var nextEmit = DateTime.MinValue; var lastLoopStart = DateTime.UtcNow; var enumerator = SubscriptionSynchronizer .Sync(SubscriptionManager.DataFeedSubscriptions, cancellationToken) .GetEnumerator(); var previousWasTimePulse = false; while (!cancellationToken.IsCancellationRequested) { var now = DateTime.UtcNow; if (!previousWasTimePulse) { if (!_newLiveDataEmitted.IsSet) { // if we just crossed into the next second let's loop again, we will flush any consolidator bar // else we will wait to be notified by the subscriptions or our scheduled event service every second if (lastLoopStart.Second == now.Second) { _realTimeScheduleEventService.ScheduleEvent(TimeSpan.FromMilliseconds(GetPulseDueTime(now)), now); _newLiveDataEmitted.Wait(); } } _newLiveDataEmitted.Reset(); } lastLoopStart = now; TimeSlice timeSlice; try { if (!enumerator.MoveNext()) { // the enumerator ended break; } timeSlice = enumerator.Current; } catch (Exception err) { Log.Error(err); // notify the algorithm about the error, so it can be reported to the user Algorithm.RunTimeError = err; Algorithm.Status = AlgorithmStatus.RuntimeError; shouldSendExtraEmptyPacket = true; break; } // check for cancellation if (timeSlice == null || cancellationToken.IsCancellationRequested) { break; } var frontierUtc = FrontierTimeProvider.GetUtcNow(); // emit on data or if we've elapsed a full second since last emit or there are security changes if (timeSlice.SecurityChanges != SecurityChanges.None || timeSlice.IsTimePulse || timeSlice.Data.Count != 0 || frontierUtc >= nextEmit) { previousWasTimePulse = timeSlice.IsTimePulse; yield return(timeSlice); // force emitting every second since the data feed is // the heartbeat of the application nextEmit = frontierUtc.RoundDown(Time.OneSecond).Add(Time.OneSecond); } } if (shouldSendExtraEmptyPacket) { // send last empty packet list before terminating, // so the algorithm manager has a chance to detect the runtime error // and exit showing the correct error instead of a timeout nextEmit = FrontierTimeProvider.GetUtcNow().RoundDown(Time.OneSecond); if (!cancellationToken.IsCancellationRequested) { var timeSlice = TimeSliceFactory.Create( nextEmit, new List <DataFeedPacket>(), SecurityChanges.None, new Dictionary <Universe, BaseDataCollection>()); yield return(timeSlice); } } enumerator.DisposeSafely(); Log.Trace("LiveSynchronizer.GetEnumerator(): Exited thread."); }
public void Reset() { _mre.Reset(); }
public IntCode Run(Action <long> output = null) { idle.Reset(); Running = true; while (pc >= 0 && pc < memory.Length && memory[pc] != 99) { int op = PCReadOpCode(); if (op == 1) { long arg1 = PCReadValue(); long arg2 = PCReadValue(); long dest = PCReadAddr(); memory[dest] = arg1 + arg2; } else if (op == 2) { long arg1 = PCReadValue(); long arg2 = PCReadValue(); long dest = PCReadAddr(); memory[dest] = arg1 * arg2; } else if (op == 3) { long dest = PCReadAddr(); idle.Set(); memory[dest] = PopInput(); idle.Reset(); } else if (op == 4) { long arg1 = PCReadValue(); output(arg1); } else if (op == 5) { long arg1 = PCReadValue(); long dest = PCReadValue(); if (arg1 != 0) { pc = (int)dest; } } else if (op == 6) { long arg1 = PCReadValue(); long dest = PCReadValue(); if (arg1 == 0) { pc = (int)dest; } } else if (op == 7) { long arg1 = PCReadValue(); long arg2 = PCReadValue(); long dest = PCReadAddr(); memory[dest] = (arg1 < arg2) ? 1 : 0; } else if (op == 8) { long arg1 = PCReadValue(); long arg2 = PCReadValue(); long dest = PCReadAddr(); memory[dest] = (arg1 == arg2) ? 1 : 0; } else if (op == 9) { relbase += PCReadValue(); } else { throw new Exception("Intcode opcode error"); } } if (memory[pc] != 99) { throw new Exception("Intcode pc address error"); } Running = false; return(this); }
/// <summary> /// Dequeue a WorkItem for processing /// </summary> /// <returns>A WorkItem or null if the queue has stopped</returns> public WorkItem Dequeue() { SpinWait sw = new SpinWait(); do { WorkItemQueueState cachedState = State; if (cachedState == WorkItemQueueState.Stopped) { return(null); // Tell worker to terminate } int cachedRemoveId = _removeId; int cachedAddId = _addId; // Empty case (or paused) if (cachedRemoveId == cachedAddId || cachedState == WorkItemQueueState.Paused) { // Spin a few times to see if something changes if (sw.Count <= SPIN_COUNT) { sw.SpinOnce(); } else { // Reset to wait for an enqueue _mreAdd.Reset(); // Recheck for an enqueue to avoid a Wait if ((cachedRemoveId != _removeId || cachedAddId != _addId) && cachedState != WorkItemQueueState.Paused) { // Queue is not empty, set the event _mreAdd.Set(); continue; } // Wait for something to happen _mreAdd.Wait(500); } continue; } // Validate that we are the current dequeuer if (Interlocked.CompareExchange(ref _removeId, cachedRemoveId + 1, cachedRemoveId) != cachedRemoveId) { continue; } // Dequeue our work item WorkItem work = null; while (work == null) { foreach (var q in _innerQueues) { if (q.TryDequeue(out work)) { break; } } } // Add to items processed using CAS Interlocked.Increment(ref _itemsProcessed); return(work); } while (true); }
public static void Reset() { TriggeredCount = 0; triggered.Reset(); }
public void Pausar() { _pauseEvent.Reset(); _pauseEvent.Wait(TokenSource.Token); }
private void WorkerWorker() { var flushMessages = new Queue <WorkerMessage>(); bool changed = false; var lastUpdateTime = DateTime.Now; while (_workerQueueChanged.Wait(1000)) { // Reset event and handle all messages in the queue _workerQueueChanged.Reset(); while (true) { WorkerMessage msg; lock (_workerQueue) { if (_workerQueue.Count == 0) { break; } msg = _workerQueue.Dequeue(); Debug.WriteLine(string.Format("{2} Processing msg... {0} {1}", DateTime.Now, msg, GetType())); } if (msg is WorkerMessage.FlushMessage) { // Keep flush messages until we've exited the loop flushMessages.Enqueue(msg); } else { // Apply the message to our collection changed |= msg.Apply(_items, _itemsLock); } Debug.WriteLine(string.Format("{2} Done processing msg... {0} {1}", DateTime.Now, msg, GetType())); // Every second, we want to force another update if (changed) { var currentTime = DateTime.Now; if ((currentTime - lastUpdateTime).TotalMilliseconds > 1000) { if (Refresh()) { lastUpdateTime = currentTime; changed = false; } } } } Debug.WriteLine(string.Format("Looping to wait... {0}", DateTime.Now)); } // Handle any changes that weren't handled in the loop if (changed) { Debug.WriteLine(string.Format("Refreshing... {0}", DateTime.Now)); Refresh(); } // Notify all the flush messages we received Debug.WriteLine(string.Format("Flushing... {0}", DateTime.Now)); while (flushMessages.Any()) { var msg = flushMessages.Dequeue(); msg.Apply(_items, _itemsLock); } Debug.WriteLine(string.Format("Done flushing... {0}", DateTime.Now)); }
void RACWorker_DoWork(object sender, DoWorkEventArgs e) { UInt64 deltaTimeInQueue; String threadName = "RossiAlphaAnalyzer_" + rossiAlphaGateWidth; Thread.CurrentThread.Name = threadName; #if USE_SPINTIME spinTimeReady = false; #endif while (keepRunning == true) { isReadyToAnalyze = true; #if USE_SPINTIME if (spinTimeReady) { StartSpinCount(); } #endif waitingForMessage.Wait(); //wait for some other thread to place neutron data in this object and signal this worker to analyze #if USE_SPINTIME if (spinTimeReady) { EndSpinCount(); } else { spinTimeReady = true; } #endif if (keepRunning == true) { UInt64 eventTime; UInt32 eventNeutrons; UInt32 eventNumNeutrons; int j; for (j = 0; j < numEventsThisBlock; j++) { eventTime = inputEventTime[j]; eventNeutrons = inputEventNeutrons[j]; eventNumNeutrons = inputEventNumNeutrons[j]; //fill in these new data at the tail of the circular linked list, //remembering that endOfNeutronEventList points to the next EMPTY struct in the list //INCLUDING at the beginning when the head and tail point to the same struct endOfList.FillEventWithData(eventTime, eventNeutrons, eventNumNeutrons); //check to see if the circular list will overflow if (endOfList.next.serialNumber == startOfList.serialNumber) { int i; RossiAlphaCircularNeutronEvent anEvent; RossiAlphaCircularNeutronEvent nextEvent; //if stack would overflow, add RawAnalysisProperties.circularListBlockIncrement neutron events at this spot in the stack... anEvent = endOfList; nextEvent = endOfList.next; for (i = 0; i < RawAnalysisProperties.circularListBlockIncrement; i++) { anEvent.next = new RossiAlphaCircularNeutronEvent(i + numObjectsInCircularLinkedList); anEvent = anEvent.next; } anEvent.next = nextEvent; //patch the circular linked list back together numObjectsInCircularLinkedList += RawAnalysisProperties.circularListBlockIncrement; //increase the record of the number of structs in the circular list } //move endOfNeutronEventList to the next empty struct endOfList = endOfList.next; //for fun, count how many times we have lapped the circular list in this experiment if (endOfList.serialNumber == 0) { numCircuits++; } //see if oldest event in the queue is expiring, //and while there are expiring events calculate the RossiAlpha statistics for those events deltaTimeInQueue = eventTime - startOfList.eventTime; while (deltaTimeInQueue > rossiAlphaWindowWidth) { //record the time of the expiring gate from the startOfList event, the total measured time for this experiment totalRossiAlphaAnalysisTime = startOfList.eventTime + rossiAlphaWindowWidth; //do RossiAlpha analysis here, accumulating statistics //add up how many neutrons there were in each RossiAlpha gate from the time of the expiring event int whichBin; UInt64 deltaTime; RossiAlphaCircularNeutronEvent anEvent; //skip the event at the head of the list. //To match data from the legacy code, start with the neutron event following this expiring head event. anEvent = startOfList.next; while (anEvent.serialNumber != endOfList.serialNumber) //...that is, until we reach the end of the list... { //Find the lowest bin with end time greater than the time of anEvent. deltaTime = anEvent.eventTime - startOfList.eventTime; whichBin = (int)(Math.Ceiling((double)deltaTime / (double)rossiAlphaGateWidth) + 0.1); if (whichBin < RawAnalysisProperties.numRAGatesPerWindow) //then this event falls into a bin; add this event's neutrons to that bin { neutronsPerRossiAlphaGate[whichBin] += anEvent.numNeutrons; //go to the next event anEvent = anEvent.next; } else { anEvent = endOfList; //abort the loop by going to the end of the list } } //remove expiring oldest event from the stack startOfList = startOfList.next; //re-calculate the delta time in the stack deltaTimeInQueue = eventTime - startOfList.eventTime; } //END of handling an individual NeutronEvent } //END of handling this block of events //prepare this thread's wait condition so will wait for a message //before telling master thread this thread's analysis is complete waitingForMessage.Reset(); } //END of if(keepRunning) else { //The master thread has cleared the keepRunning flag, so this worker is exiting //Do any cleanup etc. here. } } //END of while(keepRunning) }
public void MultiAccessSerializationAsync() { var cache1 = new MockTokenCache(); var helper1 = new MsalCacheHelper( cache1, new MsalCacheStorage(s_storageCreationProperties, _logger), _logger); var cache2 = new MockTokenCache(); var helper2 = new MsalCacheHelper( cache2, new MsalCacheStorage(s_storageCreationProperties, _logger), _logger); //Test signalling thread 1 var resetEvent1 = new ManualResetEventSlim(initialState: false); //Test signalling thread 2 var resetEvent2 = new ManualResetEventSlim(initialState: false); //Thread 1 signalling test var resetEvent3 = new ManualResetEventSlim(initialState: false); // Thread 2 signalling test var resetEvent4 = new ManualResetEventSlim(initialState: false); var thread1 = new Thread(() => { var args = new TokenCacheNotificationArgs { TokenCache = cache1 }; helper1.BeforeAccessNotification(args); resetEvent3.Set(); resetEvent1.Wait(); helper1.AfterAccessNotification(args); }); var thread2 = new Thread(() => { var args = new TokenCacheNotificationArgs { TokenCache = cache2 }; helper2.BeforeAccessNotification(args); resetEvent4.Set(); resetEvent2.Wait(); helper2.AfterAccessNotification(args); resetEvent4.Set(); }); // Let thread 1 start and get the lock thread1.Start(); resetEvent3.Wait(); // Start thread 2 and give it enough time to get blocked on the lock thread2.Start(); Thread.Sleep(5000); // Make sure helper1 has the lock still, and helper2 doesn't Assert.IsNotNull(helper1.CacheLock); Assert.IsNull(helper2.CacheLock); // Allow thread1 to give up the lock, and wait for helper2 to get it resetEvent1.Set(); resetEvent4.Wait(); resetEvent4.Reset(); // Make sure helper1 gave it up properly, and helper2 now owns the lock Assert.IsNull(helper1.CacheLock); Assert.IsNotNull(helper2.CacheLock); // Allow thread2 to give up the lock, and wait for it to complete resetEvent2.Set(); resetEvent4.Wait(); // Make sure thread2 cleaned up after itself as well Assert.IsNull(helper2.CacheLock); }
/// <summary> /// Loops forever, reading data from client. /// Fires event for each complete game packet received. /// </summary> private void Read_Thread() { try { //vars byte[] buffer = new byte[8192]; NetworkStream stream = _client.GetStream(); //internal async callback function void callback(IAsyncResult ar) { try { //stop reading? if (_stop) { return; } //end read int bytesRead = stream.EndRead(ar); //lock queue lock (_incomingQueue) { //add new bytes to queue for (int i = 0; i < bytesRead; i++) { _incomingQueue.Add(buffer[i]); } //set signal if (bytesRead > 0) { _readSignal.Set(); } } //begin next read stream.BeginRead(buffer, 0, buffer.Length, new AsyncCallback(callback), null); } catch (IOException ioex) { _stop = true; if ((ioex.InnerException != null) && (ioex.InnerException is SocketException sex)) { Log.Write($"Connection to '{_remoteIP}' closed: {sex.SocketErrorCode}"); } else { ErrorHandler.LogError(ioex); } } catch (Exception ex) { _stop = true; ErrorHandler.LogError(ex); } } //begin first read stream.BeginRead(buffer, 0, buffer.Length, new AsyncCallback(callback), null); //loop forever, pulling complete packets out of incoming queue while (true) { //wait new data in queue, or one second _readSignal.Wait(1000); _readSignal.Reset(); //read data, if it exists ReadData(); //end thread? if (_stop) { break; } } } catch (Exception ex) { _stop = true; Log.Write("ReadThread: Reading or processing data"); ErrorHandler.LogError(ex); } }
public static void WaitNotificationTest() { ThreadTestHelpers.RunTestInBackgroundThread(() => { var tsc = new TestSynchronizationContext(); SynchronizationContext.SetSynchronizationContext(tsc); Assert.Same(tsc, SynchronizationContext.Current); var e = new ManualResetEvent(false); tsc.WaitAction = () => e.Set(); Assert.False(tsc.IsWaitNotificationRequired()); Assert.False(e.WaitOne(0)); tsc.SetWaitNotificationRequired(); Assert.True(tsc.IsWaitNotificationRequired()); Assert.True(e.WaitOne(0)); var mres = new ManualResetEventSlim(); tsc.WaitAction = () => mres.Set(); mres.Reset(); mres.CheckedWait(); e.Reset(); tsc.WaitAction = () => e.Set(); SynchronizationContext.SetSynchronizationContext(new TestSynchronizationContext()); Assert.False(e.WaitOne(0)); SynchronizationContext.SetSynchronizationContext(tsc); Assert.True(e.WaitOne(0)); e.Reset(); e.CheckedWait(); e.Reset(); var lockObj = new object(); var lockAcquiredFromBackground = new AutoResetEvent(false); Action waitForThread; Thread t = ThreadTestHelpers.CreateGuardedThread(out waitForThread, () => { lock (lockObj) { lockAcquiredFromBackground.Set(); e.CheckedWait(); } }); t.IsBackground = true; t.Start(); lockAcquiredFromBackground.CheckedWait(); Assert.True(Monitor.TryEnter(lockObj, ThreadTestHelpers.UnexpectedTimeoutMilliseconds)); Monitor.Exit(lockObj); waitForThread(); e.Reset(); var m = new Mutex(); t = ThreadTestHelpers.CreateGuardedThread(out waitForThread, () => { m.CheckedWait(); try { lockAcquiredFromBackground.Set(); e.CheckedWait(); } finally { m.ReleaseMutex(); } }); t.IsBackground = true; t.Start(); lockAcquiredFromBackground.CheckedWait(); m.CheckedWait(); m.ReleaseMutex(); waitForThread(); }); }
internal void SetNotComplete() { Interlocked.Exchange(ref _awaitableState, _awaitableIsNotCompleted); _manualResetEvent.Reset(); }
internal void SetState(RaftEngineState state) { if (state == State) { return; } if (State == RaftEngineState.Leader) { _leaderSelectedEvent.Reset(); } var oldState = State; if (StateBehavior != null) { StateBehavior.Dispose(); } switch (state) { case RaftEngineState.Follower: case RaftEngineState.FollowerAfterStepDown: StateBehavior = new FollowerStateBehavior(this, state == RaftEngineState.FollowerAfterStepDown); break; case RaftEngineState.CandidateByRequest: StateBehavior = new CandidateStateBehavior(this, true); //setting state before calling election because the state may change to leader before //we set it to CandidateByRequest AssertStateAndRaiseStateChanged(state, oldState); StateBehavior.HandleTimeout(); return; case RaftEngineState.Candidate: StateBehavior = new CandidateStateBehavior(this, false); //setting state before calling election because the state may change to leader before //we set it to CandidateStateBehavior AssertStateAndRaiseStateChanged(state, oldState); StateBehavior.HandleTimeout(); return; case RaftEngineState.SnapshotInstallation: StateBehavior = new SnapshotInstallationStateBehavior(this); break; case RaftEngineState.Leader: StateBehavior = new LeaderStateBehavior(this); CurrentLeader = Name; OnElectedAsLeader(); break; case RaftEngineState.SteppingDown: StateBehavior = new SteppingDownStateBehavior(this); CurrentLeader = Name; break; default: throw new ArgumentOutOfRangeException(state.ToString()); } AssertStateAndRaiseStateChanged(state, oldState); }
/// <summary> /// 安全停止接收消费 /// </summary> public void SafeStopReceive() { RabbitChannel.BasicCancel(consumerTag); StopLock.Wait(); StopLock.Reset(); }
public int Run( string cmd, string arguments, Action <string> onStandardOutput, Action <string> onStandardError, string workingDirectory, TimeSpan watchDogTimeout ) { Log($"Running command: {cmd} {arguments.ToString()}"); ProcessStartInfo startInfo = new ProcessStartInfo { CreateNoWindow = true, UseShellExecute = false, RedirectStandardOutput = true, RedirectStandardError = true, FileName = cmd, Arguments = arguments }; if (!string.IsNullOrWhiteSpace(workingDirectory)) { startInfo.WorkingDirectory = workingDirectory; } using (ManualResetEventSlim progressMadeEvent = new ManualResetEventSlim(false)) { using (Process commandProcess = new Process()) { commandProcess.StartInfo = startInfo; commandProcess.OutputDataReceived += (s, e) => { if (string.IsNullOrEmpty(e.Data)) { return; } progressMadeEvent.Set(); Console.WriteLine(e.Data); onStandardOutput?.Invoke(e.Data); }; commandProcess.ErrorDataReceived += (s, e) => { if (string.IsNullOrEmpty(e.Data)) { return; } progressMadeEvent.Set(); Console.Error.WriteLine(e.Data); onStandardError?.Invoke(e.Data); }; bool keepGoing = true; object keepGoingLock = new object(); bool GetKeepGoing() { lock ( keepGoingLock ) { return(keepGoing); } } commandProcess.EnableRaisingEvents = true; commandProcess.Exited += (s, e) => { Log($"Process '{startInfo.FileName} {startInfo.Arguments}' exited"); lock ( keepGoingLock ) { keepGoing = false; } progressMadeEvent.Set(); }; int exitCode = -1; try { commandProcess.Start(); commandProcess.BeginOutputReadLine(); commandProcess.BeginErrorReadLine(); while (GetKeepGoing()) { if (progressMadeEvent.Wait(watchDogTimeout, this._cancelToken) == false) { throw new TimeoutException( $"It has been more than {watchDogTimeout.TotalSeconds} seconds since we got an update from the Process. Possible broken Pipe. Killing process" ); } progressMadeEvent.Reset(); // So we don't eat our CPU, do a delay. Task.Delay(500, this._cancelToken); } commandProcess.WaitForExit(); } catch (Win32Exception) { throw new MigrateException($"Command {cmd} does not exit. Did you install it or add it to the Environment path?"); } catch (OperationCanceledException) { Log("CTRL+C Received"); commandProcess.Kill(true); commandProcess.WaitForExit(); throw; } catch (TimeoutException) { commandProcess.Kill(true); commandProcess.WaitForExit(); throw; } finally { exitCode = commandProcess.ExitCode; commandProcess.Close(); commandProcess.Dispose(); } return(exitCode); } } }
public void DocumentRetrieverSubscribtionsShouldWork() { using (NewRemoteDocumentStore(databaseName: "Northwind")) { var manualResetEventSlim = new ManualResetEventSlim(); var server = servers[0]; var systemDatabase = server.SystemDatabase; var database = AsyncHelpers.RunSync(() => server.Server.GetDatabaseInternal("Northwind")); var retriever = database.ConfigurationRetriever; retriever.SubscribeToConfigurationDocumentChanges(PeriodicExportSetup.RavenDocumentKey, manualResetEventSlim.Set); systemDatabase .Documents .Put( Constants.Global.PeriodicExportDocumentName, null, RavenJObject.FromObject(new PeriodicExportSetup { AwsRegionEndpoint = "e1", AzureStorageContainer = "c1", Disabled = true, FullBackupIntervalMilliseconds = 17, GlacierVaultName = "g1", IntervalMilliseconds = 12, LocalFolderName = "f1", S3BucketName = "s1" }), new RavenJObject(), null); if (manualResetEventSlim.Wait(TimeSpan.FromSeconds(10)) == false) { throw new InvalidOperationException("Waited for 10 seconds for notification."); } manualResetEventSlim.Reset(); database .Documents .Put( PeriodicExportSetup.RavenDocumentKey, null, RavenJObject.FromObject(new PeriodicExportSetup { AwsRegionEndpoint = "e2", AzureStorageContainer = "c2", Disabled = false, FullBackupIntervalMilliseconds = 2, GlacierVaultName = "g2", IntervalMilliseconds = 16, LocalFolderName = "f2", S3BucketName = "s2" }), new RavenJObject(), null); if (manualResetEventSlim.Wait(TimeSpan.FromSeconds(10)) == false) { throw new InvalidOperationException("Waited for 10 seconds for notification."); } } }
public async Task RavenDB_3172() { using (var store = GetDocumentStore()) { CreateRdbmsSchema(store); var eventSlim = new ManualResetEventSlim(false); var database = await GetDatabase(store.DefaultDatabase); database.SqlReplicationLoader.AfterReplicationCompleted += statistics => { if (statistics.SuccessCount != 0) { eventSlim.Set(); } }; using (var session = store.OpenAsyncSession()) { await session.StoreAsync(new Order { Id = "orders/1", OrderLines = new List <OrderLine> { new OrderLine { Cost = 3, Product = "Milk", Quantity = 3 }, new OrderLine { Cost = 4, Product = "Bear", Quantity = 2 }, } }); await session.SaveChangesAsync(); } await SetupSqlReplication(store, defaultScript, insertOnly : true); eventSlim.Wait(TimeSpan.FromMinutes(5)); AssertCounts(1, 2, store); eventSlim.Reset(); using (var session = store.OpenAsyncSession()) { var order = await session.LoadAsync <Order>("orders/1"); order.OrderLines.Add(new OrderLine { Cost = 5, Product = "Sugar", Quantity = 7 }); await session.SaveChangesAsync(); } eventSlim.Wait(TimeSpan.FromMinutes(5)); // we end up with duplicates AssertCounts(2, 5, store); } }
private void ReadFromQueue(object o) { try{ _queueStats.Start(); Thread.BeginThreadAffinity(); // ensure we are not switching between OS threads. Required at least for v8. while (!_stop) { Message msg = null; try { if (!_queue.TryDequeue(out msg)) { _starving = true; _queueStats.EnterIdle(); _msgAddEvent.Wait(100); _msgAddEvent.Reset(); _starving = false; } else { _queueStats.EnterBusy(); #if DEBUG _queueStats.Dequeued(msg); #endif var cnt = _queue.Count; _queueStats.ProcessingStarted(msg.GetType(), cnt); if (_watchSlowMsg) { var start = DateTime.UtcNow; _consumer.Handle(msg); var elapsed = DateTime.UtcNow - start; if (elapsed > _slowMsgThreshold) { Log.Trace("SLOW QUEUE MSG [{queue}]: {message} - {elapsed}ms. Q: {prevQueueCount}/{curQueueCount}.", Name, _queueStats.InProgressMessage.Name, (int)elapsed.TotalMilliseconds, cnt, _queue.Count); if (elapsed > QueuedHandler.VerySlowMsgThreshold && !(msg is SystemMessage.SystemInit)) { Log.Error("---!!! VERY SLOW QUEUE MSG [{queue}]: {message} - {elapsed}ms. Q: {prevQueueCount}/{curQueueCount}.", Name, _queueStats.InProgressMessage.Name, (int)elapsed.TotalMilliseconds, cnt, _queue.Count); } } } else { _consumer.Handle(msg); } _queueStats.ProcessingEnded(1); } } catch (Exception ex) { Log.ErrorException(ex, "Error while processing message {message} in queued handler '{queue}'.", msg, Name); #if DEBUG throw; #endif } } } catch (Exception ex) { _tcs.TrySetException(ex); throw; } finally{ _queueStats.Stop(); _stopped.Set(); _queueMonitor.Unregister(this); Thread.EndThreadAffinity(); } }
public ulong Evaluate(ulong n, ulong x0, ulong xmax) { if (x0 > xmax) { return(0); } if (n <= nMaxSimple) { return((ulong)manualAlgorithm.Evaluate(n, x0, xmax)); } if (threads == 0) { stack = new Stack <Region>(); } else { queue = new BlockingCollection <Region>(); } sum = 0; #if RECORD_SIZES amax = 0; bmax = 0; cmax = 0; #endif if (threads == 0) { AddToSum(EvaluateInternal(n, x0, xmax)); if (xmanual > 1) { AddToSum((ulong)manualAlgorithm.Evaluate(n, x0, 2 * xmanual - 3)); } return(sum); } // Create consumers. var consumers = threads; var tasks = new Task[consumers]; for (var consumer = 0; consumer < consumers; consumer++) { var thread = consumer; tasks[consumer] = Task.Factory.StartNew(() => ConsumeRegions(thread)); } // Produce work items. unprocessed = 1; finished.Reset(); AddToSum(Processed(EvaluateInternal(n, x0, xmax))); finished.Wait(); queue.CompleteAdding(); // Add manual portion. if (xmanual > 1) { AddToSum((ulong)manualAlgorithm.Evaluate(n, x0, 2 * xmanual - 3)); } // Wait for completion. Task.WaitAll(tasks); #if RECORD_SIZES Console.WriteLine("amax = {0}, bmax = {1}, cmax = {2}", amax, bmax, cmax); #endif return(sum); }
public void Execute(int task) { this.task = task; waitFlag.Reset(); runFlag.Set(); }
/// <summary> /// Immediately puts the thread to sleep. /// No actions can be dequeued until a call to <see cref="Wake"/> is made. /// </summary> public void Sleep() { threadSleepEvent.Reset(); }
private async Task RunPeerUpdateLoop() { int loopCount = 0; long previousActivePeersCount = 0; while (true) { try { if (loopCount++ % 100 == 0) { if (_logger.IsTrace) { _logger.Trace($"Running peer update loop {loopCount - 1} - active: {_activePeers.Count} | candidates : {_peerPool.CandidatePeerCount}"); } } try { CleanupCandidatePeers(); } catch (Exception e) { if (_logger.IsDebug) { _logger.Error("Candidate peers cleanup failed", e); } } _peerUpdateRequested.Wait(_cancellationTokenSource.Token); _peerUpdateRequested.Reset(); if (!_isStarted) { continue; } if (AvailableActivePeersCount == 0) { continue; } Interlocked.Exchange(ref _tryCount, 0); Interlocked.Exchange(ref _newActiveNodes, 0); Interlocked.Exchange(ref _failedInitialConnect, 0); Interlocked.Exchange(ref _connectionRounds, 0); SelectAndRankCandidates(); List <Peer> remainingCandidates = _currentSelection.Candidates; if (!remainingCandidates.Any()) { continue; } if (_cancellationTokenSource.IsCancellationRequested) { break; } int currentPosition = 0; while (true) { if (_cancellationTokenSource.IsCancellationRequested) { break; } int nodesToTry = Math.Min(remainingCandidates.Count - currentPosition, AvailableActivePeersCount); if (nodesToTry <= 0) { break; } ActionBlock <Peer> workerBlock = new ActionBlock <Peer>( SetupPeerConnection, new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = _parallelism, CancellationToken = _cancellationTokenSource.Token }); for (int i = 0; i < nodesToTry; i++) { await workerBlock.SendAsync(remainingCandidates[currentPosition + i]); } currentPosition += nodesToTry; workerBlock.Complete(); // Wait for all messages to propagate through the network. workerBlock.Completion.Wait(); Interlocked.Increment(ref _connectionRounds); } if (_logger.IsTrace) { int activePeersCount = _activePeers.Count; if (activePeersCount != previousActivePeersCount) { string countersLog = string.Join(", ", _currentSelection.Counters.Select(x => $"{x.Key.ToString()}: {x.Value}")); _logger.Trace($"RunPeerUpdate | {countersLog}, Incompatible: {GetIncompatibleDesc(_currentSelection.Incompatible)}, EligibleCandidates: {_currentSelection.Candidates.Count()}, " + $"Tried: {_tryCount}, Rounds: {_connectionRounds}, Failed initial connect: {_failedInitialConnect}, Established initial connect: {_newActiveNodes}, " + $"Current candidate peers: {_peerPool.CandidatePeerCount}, Current active peers: {_activePeers.Count} " + $"[InOut: {_activePeers.Count(x => x.Value.OutSession != null && x.Value.InSession != null)} | " + $"[Out: {_activePeers.Count(x => x.Value.OutSession != null)} | " + $"In: {_activePeers.Count(x => x.Value.InSession != null)}]"); } previousActivePeersCount = activePeersCount; } if (_logger.IsTrace) { if (_logCounter % 5 == 0) { string nl = Environment.NewLine; _logger.Trace($"{nl}{nl}All active peers: {nl} {string.Join(nl, _activePeers.Values.Select(x => $"{x.Node:s} | P2P: {_stats.GetOrAdd(x.Node).DidEventHappen(NodeStatsEventType.P2PInitialized)} | Eth62: {_stats.GetOrAdd(x.Node).DidEventHappen(NodeStatsEventType.Eth62Initialized)} | {_stats.GetOrAdd(x.Node).P2PNodeDetails?.ClientId} | {_stats.GetOrAdd(x.Node).ToString()}"))} {nl}{nl}"); } _logCounter++; } if (_activePeers.Count < MaxActivePeers) { _peerUpdateRequested.Set(); } } catch (AggregateException e) when(e.InnerExceptions.Any(inner => inner is OperationCanceledException)) { if (_logger.IsInfo) { _logger.Info("Peer update loop canceled."); } break; } catch (OperationCanceledException) { if (_logger.IsInfo) { _logger.Info("Peer update loop canceled"); } break; } catch (Exception e) { if (_logger.IsError) { _logger.Error("Peer update loop failure", e); } break; } } }
public void ExecuteReaderWithUpdates(Action <IDataRecord, DbOperation> processRecord) { lock (_stopLocker) { if (_disposing) { return; } _stopHandle.Reset(); } var useNotifications = _dbBehavior.StartSqlDependencyListener(); var delays = _dbBehavior.UpdateLoopRetryDelays; for (var i = 0; i < delays.Count; i++) { if (i == 0 && useNotifications) { // Reset the state to ProcessingUpdates if this is the start of the loop. // This should be safe to do here without Interlocked because the state is protected // in the other two cases using Interlocked, i.e. there should only be one instance of // this running at any point in time. _notificationState = NotificationState.ProcessingUpdates; } Tuple <int, int> retry = delays[i]; var retryDelay = retry.Item1; var retryCount = retry.Item2; for (var j = 0; j < retryCount; j++) { if (_disposing) { Stop(null); return; } if (retryDelay > 0) { Trace.TraceVerbose("{0}Waiting {1}ms before checking for messages again", TracePrefix, retryDelay); Thread.Sleep(retryDelay); } var recordCount = 0; try { recordCount = ExecuteReader(processRecord); Queried(); } catch (Exception ex) { Trace.TraceError("{0}Error in SQL receive loop: {1}", TracePrefix, ex); Faulted(ex); } if (recordCount > 0) { Trace.TraceVerbose("{0}{1} records received", TracePrefix, recordCount); // We got records so start the retry loop again i = -1; break; } Trace.TraceVerbose("{0}No records received", TracePrefix); var isLastRetry = i == delays.Count - 1 && j == retryCount - 1; if (isLastRetry) { // Last retry loop iteration if (!useNotifications) { // Last retry loop and we're not using notifications so just stay looping on the last retry delay j = j - 1; } else { // No records after all retries, set up a SQL notification try { Trace.TraceVerbose("{0}Setting up SQL notification", TracePrefix); recordCount = ExecuteReader(processRecord, command => { _dbBehavior.AddSqlDependency(command, e => SqlDependency_OnChange(e, processRecord)); }); Queried(); if (recordCount > 0) { Trace.TraceVerbose("{0}Records were returned by the command that sets up the SQL notification, restarting the receive loop", TracePrefix); i = -1; break; // break the inner for loop } else { var previousState = Interlocked.CompareExchange(ref _notificationState, NotificationState.AwaitingNotification, NotificationState.ProcessingUpdates); if (previousState == NotificationState.AwaitingNotification) { Trace.TraceError("{0}A SQL notification was already running. Overlapping receive loops detected, this should never happen. BUG!", TracePrefix); return; } if (previousState == NotificationState.NotificationReceived) { // Failed to change _notificationState from ProcessingUpdates to AwaitingNotification, it was already NotificationReceived Trace.TraceVerbose("{0}The SQL notification fired before the receive loop returned, restarting the receive loop", TracePrefix); i = -1; break; // break the inner for loop } } Trace.TraceVerbose("{0}No records received while setting up SQL notification", TracePrefix); // We're in a wait state for a notification now so check if we're disposing lock (_stopLocker) { if (_disposing) { _stopHandle.Set(); } } } catch (Exception ex) { Trace.TraceError("{0}Error in SQL receive loop: {1}", TracePrefix, ex); Faulted(ex); // Re-enter the loop on the last retry delay j = j - 1; if (retryDelay > 0) { Trace.TraceVerbose("{0}Waiting {1}ms before checking for messages again", TracePrefix, retryDelay); Thread.Sleep(retryDelay); } } } } } } Trace.TraceVerbose("{0}Receive loop exiting", TracePrefix); }
private async Task CopyModelAsCsvToStreamAsync(SecurityPrincipal securityPrincipal, NameValueCollection requestParameters, Stream responseStream, CancellationToken cancellationToken) { const double DefaultFrameRate = 30; const int DefaultTimestampSnap = 0; string dateTimeFormat = Program.Host.Model.Global.DateTimeFormat; // TODO: Improve operation for large point lists: // Pick-up "POST"ed parameters with a "genurl" param, then cache parameters // in a memory cache and return the unique URL (a string instead of a file) // with a "download" param and unique ID associated with cached parameters. // Then extract params based on unique ID and follow normal steps... // Note TSTolerance is in ms string pointIDsParam = requestParameters["PointIDs"]; string startTimeParam = requestParameters["StartTime"]; string endTimeParam = requestParameters["EndTime"]; string timestampSnapParam = requestParameters["TSSnap"]; string frameRateParam = requestParameters["FrameRate"]; string alignTimestampsParam = requestParameters["AlignTimestamps"]; string missingAsNaNParam = requestParameters["MissingAsNaN"]; string fillMissingTimestampsParam = requestParameters["FillMissingTimestamps"]; string instanceName = requestParameters["InstanceName"]; string toleranceParam = requestParameters["TSTolerance"]; ulong[] pointIDs; string headers; if (string.IsNullOrEmpty(pointIDsParam)) { throw new ArgumentNullException("PointIDs", "Cannot export data: no values were provided in \"PointIDs\" parameter."); } try { pointIDs = pointIDsParam.Split(',').Select(ulong.Parse).ToArray(); Array.Sort(pointIDs); } catch (Exception ex) { throw new ArgumentNullException("PointIDs", $"Cannot export data: failed to parse \"PointIDs\" parameter value \"{pointIDsParam}\": {ex.Message}"); } if (string.IsNullOrEmpty(startTimeParam)) { throw new ArgumentNullException("StartTime", "Cannot export data: no \"StartTime\" parameter value was specified."); } if (string.IsNullOrEmpty(pointIDsParam)) { throw new ArgumentNullException("EndTime", "Cannot export data: no \"EndTime\" parameter value was specified."); } DateTime startTime, endTime; try { startTime = DateTime.ParseExact(startTimeParam, dateTimeFormat, null, DateTimeStyles.AdjustToUniversal); } catch (Exception ex) { throw new ArgumentException($"Cannot export data: failed to parse \"StartTime\" parameter value \"{startTimeParam}\". Expected format is \"{dateTimeFormat}\". Error message: {ex.Message}", "StartTime", ex); } try { endTime = DateTime.ParseExact(endTimeParam, dateTimeFormat, null, DateTimeStyles.AdjustToUniversal); } catch (Exception ex) { throw new ArgumentException($"Cannot export data: failed to parse \"EndTime\" parameter value \"{endTimeParam}\". Expected format is \"{dateTimeFormat}\". Error message: {ex.Message}", "EndTime", ex); } if (startTime > endTime) { throw new ArgumentOutOfRangeException("StartTime", "Cannot export data: start time exceeds end time."); } using (DataContext dataContext = new DataContext()) { // Validate current user has access to requested data if (!dataContext.UserIsInRole(securityPrincipal, s_minimumRequiredRoles)) { throw new SecurityException($"Cannot export data: access is denied for user \"{Thread.CurrentPrincipal.Identity?.Name ?? "Undefined"}\", minimum required roles = {s_minimumRequiredRoles.ToDelimitedString(", ")}."); } headers = GetHeaders(dataContext, pointIDs.Select(id => (int)id)); } if (!double.TryParse(frameRateParam, out double frameRate)) { frameRate = DefaultFrameRate; } if (!int.TryParse(timestampSnapParam, out int timestampSnap)) { timestampSnap = DefaultTimestampSnap; } if (!double.TryParse(toleranceParam, out double tolerance)) { tolerance = 0.5; } int toleranceTicks = (int)Math.Ceiling(tolerance * Ticks.PerMillisecond); bool alignTimestamps = alignTimestampsParam?.ParseBoolean() ?? true; bool missingAsNaN = missingAsNaNParam?.ParseBoolean() ?? true; bool fillMissingTimestamps = alignTimestamps && (fillMissingTimestampsParam?.ParseBoolean() ?? false); if (string.IsNullOrEmpty(instanceName)) { instanceName = TrendValueAPI.DefaultInstanceName; } LocalOutputAdapter.Instances.TryGetValue(instanceName, out LocalOutputAdapter adapter); HistorianServer serverInstance = adapter?.Server; if (serverInstance == null) { throw new InvalidOperationException($"Cannot export data: failed to access internal historian server instance \"{instanceName}\"."); } const int TargetBufferSize = 524288; StringBuilder readBuffer = new StringBuilder(TargetBufferSize * 2); ManualResetEventSlim bufferReady = new ManualResetEventSlim(false); List <string> writeBuffer = new List <string>(); object writeBufferLock = new object(); bool readComplete = false; Task readTask = Task.Factory.StartNew(() => { try { using (SnapClient connection = SnapClient.Connect(serverInstance.Host)) { Dictionary <ulong, int> pointIDIndex = new Dictionary <ulong, int>(pointIDs.Length); float[] values = new float[pointIDs.Length]; for (int i = 0; i < pointIDs.Length; i++) { pointIDIndex.Add(pointIDs[i], i); } for (int i = 0; i < values.Length; i++) { values[i] = float.NaN; } ulong interval; if (Math.Abs(frameRate % 1) <= (double.Epsilon * 100)) { Ticks[] subseconds = Ticks.SubsecondDistribution((int)frameRate); interval = (ulong)(subseconds.Length > 1 ? subseconds[1].Value : Ticks.PerSecond); } else { interval = (ulong)(Math.Floor(1.0d / frameRate) * Ticks.PerSecond); } ulong lastTimestamp = 0; // Write data pages SeekFilterBase <HistorianKey> timeFilter = TimestampSeekFilter.CreateFromRange <HistorianKey>(startTime, endTime); MatchFilterBase <HistorianKey, HistorianValue> pointFilter = PointIdMatchFilter.CreateFromList <HistorianKey, HistorianValue>(pointIDs); HistorianKey historianKey = new HistorianKey(); HistorianValue historianValue = new HistorianValue(); // Write row values function Action bufferValues = () => { readBuffer.Append(missingAsNaN ? string.Join(",", values) : string.Join(",", values.Select(val => float.IsNaN(val) ? "" : $"{val}"))); if (readBuffer.Length < TargetBufferSize) { return; } lock (writeBufferLock) writeBuffer.Add(readBuffer.ToString()); readBuffer.Clear(); bufferReady.Set(); }; using (ClientDatabaseBase <HistorianKey, HistorianValue> database = connection.GetDatabase <HistorianKey, HistorianValue>(instanceName)) { // Start stream reader for the provided time window and selected points TreeStream <HistorianKey, HistorianValue> stream = database.Read(SortedTreeEngineReaderOptions.Default, timeFilter, pointFilter); ulong timestamp = 0; // Adjust timestamp to use first timestamp as base bool adjustTimeStamp = true; long baseTime = startTime.Ticks; if (timestampSnap == 0) { adjustTimeStamp = false; baseTime = Ticks.RoundToSecondDistribution(startTime.Ticks, frameRate, startTime.Ticks - startTime.Ticks % Ticks.PerSecond); } else if (timestampSnap == 1) { adjustTimeStamp = true; } else if (timestampSnap == 2) { adjustTimeStamp = false; baseTime = startTime.Ticks; } while (stream.Read(historianKey, historianValue) && !cancellationToken.IsCancellationRequested) { if (alignTimestamps) { if (adjustTimeStamp) { adjustTimeStamp = false; baseTime = (long)historianKey.Timestamp; } // Make sure the timestamp is actually close enough to the distribution Ticks ticks = Ticks.ToSecondDistribution((long)historianKey.Timestamp, frameRate, baseTime, toleranceTicks); if (ticks == Ticks.MinValue) { continue; } timestamp = (ulong)ticks.Value; } else { timestamp = historianKey.Timestamp; } // Start a new row for each encountered new timestamp if (timestamp != lastTimestamp) { if (lastTimestamp > 0) { bufferValues(); } for (int i = 0; i < values.Length; i++) { values[i] = float.NaN; } if (fillMissingTimestamps && lastTimestamp > 0 && timestamp > lastTimestamp) { ulong difference = timestamp - lastTimestamp; if (difference > interval) { ulong interpolated = lastTimestamp; for (ulong i = 1; i < difference / interval; i++) { interpolated = (ulong)Ticks.RoundToSecondDistribution((long)(interpolated + interval), frameRate, startTime.Ticks).Value; readBuffer.Append($"{Environment.NewLine}{new DateTime((long)interpolated, DateTimeKind.Utc).ToString(dateTimeFormat)},"); bufferValues(); } } } readBuffer.Append($"{Environment.NewLine}{new DateTime((long)timestamp, DateTimeKind.Utc).ToString(dateTimeFormat)},"); lastTimestamp = timestamp; } // Save value to its column values[pointIDIndex[historianKey.PointID]] = historianValue.AsSingle; } if (timestamp > 0) { bufferValues(); } if (readBuffer.Length > 0) { lock (writeBufferLock) writeBuffer.Add(readBuffer.ToString()); } } } } finally { readComplete = true; bufferReady.Set(); } }, cancellationToken); Task writeTask = Task.Factory.StartNew(() => { using (StreamWriter writer = new StreamWriter(responseStream)) { //Ticks exportStart = DateTime.UtcNow.Ticks; string[] localBuffer; // Write column headers writer.Write(headers); while ((writeBuffer.Count > 0 || !readComplete) && !cancellationToken.IsCancellationRequested) { bufferReady.Wait(cancellationToken); bufferReady.Reset(); lock (writeBufferLock) { localBuffer = writeBuffer.ToArray(); writeBuffer.Clear(); } foreach (string buffer in localBuffer) { writer.Write(buffer); } } // Flush stream writer.Flush(); //Debug.WriteLine("Export time: " + (DateTime.UtcNow.Ticks - exportStart).ToElapsedTimeString(3)); } }, cancellationToken); await readTask; await writeTask; }
/// <summary> /// Enters the state in which waiters need to wait. /// All future waiters will block when they call the Wait method /// </summary> public void Begin() => Event?.Reset();
/// <summary> /// Mains the periodic task action. /// </summary> /// <param name="state">state object</param> /// <param name="intervalInMilliseconds">The interval in milliseconds.</param> /// <param name="delayInMilliseconds">The delay in milliseconds.</param> /// <param name="duration">The duration.</param> /// <param name="maxIterations">The max iterations.</param> /// <param name="cancelToken">The cancel token.</param> /// <param name="stopWatch">The stop watch.</param> /// <param name="synchronous">if set to <c>true</c> executes each period in a blocking fashion and each periodic execution of the task /// is included in the total duration of the Task.</param> /// <param name="wrapperAction">The wrapper action.</param> /// <param name="periodicTaskCreationOptions"><see cref="TaskCreationOptions"/> used to create a sub task for executing the <see cref="Action"/>.</param> private static void MainPeriodicTaskAction(object state, int intervalInMilliseconds, int delayInMilliseconds, int duration, int maxIterations, CancellationToken cancelToken, Stopwatch stopWatch, bool synchronous, Action <object> wrapperAction, TaskCreationOptions periodicTaskCreationOptions) { TaskCreationOptions subTaskCreationOptions = TaskCreationOptions.AttachedToParent | periodicTaskCreationOptions; CheckIfCancelled(cancelToken); if (delayInMilliseconds > 0) { Thread.Sleep(delayInMilliseconds); } if (maxIterations == 0) { return; } int iteration = 0; //////////////////////////////////////////////////////////////////////////// // using a ManualResetEventSlim as it is more efficient in small intervals. // In the case where longer intervals are used, it will automatically use // a standard WaitHandle.... // see http://msdn.microsoft.com/en-us/library/vstudio/5hbefs30(v=vs.100).aspx using (ManualResetEventSlim periodResetEvent = new ManualResetEventSlim(false)) { //////////////////////////////////////////////////////////// // Main periodic logic. Basically loop through this block // executing the action while (true) { CheckIfCancelled(cancelToken); Task subTask = Task.Factory.StartNew(wrapperAction, state, cancelToken, subTaskCreationOptions, TaskScheduler.Current); if (synchronous) { stopWatch.Start(); try { subTask.Wait(cancelToken); } catch { /* do not let an errant subtask to kill the periodic task...*/ } stopWatch.Stop(); } // use the same Timeout setting as the System.Threading.Timer, infinite timeout will execute only one iteration. if (intervalInMilliseconds == Timeout.Infinite) { break; } iteration++; if (maxIterations > 0 && iteration >= maxIterations) { break; } try { stopWatch.Start(); periodResetEvent.Wait(intervalInMilliseconds, cancelToken); stopWatch.Stop(); } finally { periodResetEvent.Reset(); } CheckIfCancelled(cancelToken); if (duration > 0 && stopWatch.ElapsedMilliseconds >= duration) { break; } } } }