protected override async Task MainLoopImplAsync(CancellationToken cancel) { cancel.ThrowIfCancellationRequested(); GoogleApi.GmailProfile profile; try { profile = await Api !.GmailGetProfileAsync(cancel); ClearLastError(); } catch (Exception ex) { SetLastError(ex); throw; } currentProfile = profile; currentAccountInfoStr = profile.emailAddress; while (true) { cancel.ThrowIfCancellationRequested(); try { InboxMessageBox box = await ReloadInternalAsync(cancel); this.InitialLoading = false; ClearLastError(); MessageBoxUpdatedCallback(box); } catch (Exception ex) { SetLastError(ex); throw; } await TaskUtil.WaitObjectsAsync( cancels : cancel._SingleArray(), timeout : Util.GenRandInterval(CoresConfig.InboxGmailAdapterSettings.ReloadInterval)); } }
public async Task <bool> FlushAsync(bool halfFlush = false, CancellationToken cancel = default) { this.Event.Set(); while (this.GrandCancel.IsCancellationRequested == false && cancel.IsCancellationRequested == false) { int num; lock (this.RecordQueue) num = this.RecordQueue.Count; if (halfFlush == false) { if (num == 0) { return(true); } } else { if (num <= (this.MaxPendingRecords / 2)) { return(true); } } if (this.GrandCancel.IsCancellationRequested) { return(false); } if (cancel.IsCancellationRequested) { return(false); } var ret = await TaskUtil.WaitObjectsAsync(timeout : 100, cancels : new CancellationToken[] { cancel, this.GrandCancel }); if (ret == ExceptionWhen.CancelException) { return(false); } } return(false); }
public async Task <ConnSock> ConnectAsync(CancellationToken cancel = default) { if (Flag.IsFirstCall() == false) { throw new ApplicationException("ConnectAsync() has been already called."); } List <Task <ConnSock> > taskList = new List <Task <ConnSock> >(); foreach (var attempt in AttemptList) { taskList.Add(attempt.ConnectAsyncInternal(this, cancel)); } if (taskList.Count == 0) { throw new ApplicationException("SpeculativeConnectorBase: The attempt list is empty."); } while (true) { var okTask = taskList.Where(x => x.IsCompletedSuccessfully).FirstOrDefault(); if (okTask != null) { // OK PostWaitEvent.Set(); taskList.ForEach(x => x._TryWait(true)); taskList.Where(x => x != okTask).Where(x => x.IsCompletedSuccessfully)._DoForEach(x => x.Result._DisposeSafe()); return(okTask._GetResult()); } taskList.Where(x => x.IsCanceled || x.IsFaulted).ToArray()._DoForEach(x => taskList.Remove(x)); if (taskList.Count == 0) { // Error throw this.ExceptionList.GetException() !; } await TaskUtil.WaitObjectsAsync(taskList.ToArray(), exceptions : ExceptionWhen.None); } }
public async Task <bool> AddAsync(LogRecord r, LogPendingTreatment pendingTreatment = LogPendingTreatment.Discard, CancellationToken pendingWaitCancel = default) { if (r.Priority == LogPriority.None) { return(true); } if (this.GrandCancel.IsCancellationRequested) { return(false); } while (MaxPendingRecords >= 1 && this.RecordQueue.Count >= this.MaxPendingRecords) { if (pendingTreatment == LogPendingTreatment.WriteForcefully) { break; } else if (pendingTreatment == LogPendingTreatment.Wait) { await TaskUtil.WaitObjectsAsync(cancels : new CancellationToken[] { pendingWaitCancel, this.GrandCancel }, events : this.WaitPendingEvent._SingleArray()); } else { return(false); } } lock (this.RecordQueue) { this.RecordQueue.Enqueue(r); } this.Event.Set(); return(true); }
// ランダムに配列した各テストを 1 秒間隔で順に実行していき、1 つでも成功したら抜ける // 1 つでも成功した場合は true、成功するまでにネットワークの状態が変化した場合は false を返す async Task <bool> StartEveryTestAsync(CancellationToken cancel, AsyncAutoResetEvent?networkChangedEvent) { int startNetworkVersion = (networkChangedEvent == null) ? 0 : TcpIp.GetHostInfo(false).InfoVersion; CancellationTokenSource cts = new CancellationTokenSource(); using (TaskUtil.CreateCombinedCancellationToken(out CancellationToken opCancel, cancel, cts.Token)) { // テストをシャッフルする var shuffledTests = Options.GetTestItemList()._Shuffle(); List <Task <bool> > runningTaskList = new List <Task <bool> >(); RefBool retBool = new RefBool(); // シャッフルしたテストを実行する int num = 0; foreach (var test in shuffledTests) { Task <bool> t = AsyncAwait(async() => { //Con.WriteDebug($"{test} - Waiting {num} secs..."); if (await opCancel._WaitUntilCanceledAsync(1000 * num)) { // キャンセルされた return(false); } int numRetry = 0; while (true) { if (opCancel.IsCancellationRequested) { return(false); } bool ret = await PerformSingleTestAsync(test, opCancel); //Con.WriteDebug($"{test} - {ret}"); if (ret) { // 成功 retBool.Set(true); // 自分自信のほか、他のタスクもすべてキャンセルする cts._TryCancelNoBlock(); return(true); } // 再試行まで待機 numRetry++; int retryInterval = Util.GenRandIntervalWithRetry(Options.RetryIntervalMin, numRetry, Options.RetryIntervalMax); if (test is InternetCheckerPingTestItem) { retryInterval = Util.GenRandIntervalWithRetry(Options.RetryIntervalMin, numRetry, Options.RetryIntervalMaxPing); } await TaskUtil.WaitObjectsAsync(cancels: opCancel._SingleArray(), events: networkChangedEvent._SingleArray(), timeout: retryInterval); if (opCancel.IsCancellationRequested) { // キャンセルされた return(false); } if (startNetworkVersion != 0) { int currentNetworkVersion = BackgroundState <PalHostNetInfo> .Current.Version; if (startNetworkVersion != currentNetworkVersion) { // ネットワーク状態が変化した // 自分自身のほか、他のタスクもすべてキャンセルする cts._TryCancelNoBlock(); return(false); } } } }); runningTaskList.Add(t); num++; } // 実行中のテストすべてを待機する await Task.WhenAll(runningTaskList); return(retBool); } }
// メインループ async Task MainLoopAsync(CancellationToken cancel) { while (cancel.IsCancellationRequested == false) { // インターネットが接続されるまで待機する if (await WaitForInternetAsync(cancel) == false) { // キャンセルされた return; } // 接続された _IsInternetConnected = true; FirstConnectedEvent.Set(true); EventListener.FireSoftly(this, NonsenseEventType.Nonsense, true); int lastNetworkVersion = TcpIp.GetHostInfo(false).InfoVersion; AsyncAutoResetEvent networkChangedEvent = new AsyncAutoResetEvent(); int eventRegisterId = TcpIp.RegisterHostInfoChangedEvent(networkChangedEvent); try { // 定期的に、現在もインターネットに接続されているかどうか確認する while (cancel.IsCancellationRequested == false) { // 一定時間待つ ただしネットワーク状態の変化が発生したときは待ちを解除する await TaskUtil.WaitObjectsAsync(cancels : cancel._SingleArray(), events : networkChangedEvent._SingleArray(), timeout : Options.CheckIntervalAfterEstablished); if (cancel.IsCancellationRequested) { break; } // 接続検査を再実行する // ただし、今度はタイムアウトを設定する CancellationTokenSource timeoutCts = new CancellationTokenSource(); timeoutCts.CancelAfter(Options.TimeoutToDetectDisconnected); bool ret = await StartEveryTestAsync(timeoutCts.Token, null); if (cancel.IsCancellationRequested) { break; } if (ret == false) { // 接続試験に失敗 (タイムアウト発生) // 切断された _IsInternetConnected = false; FirstDisconnectedEvent.Set(true); EventListener.FireSoftly(this, NonsenseEventType.Nonsense, false); break; } } } finally { TcpIp.UnregisterHostInfoChangedEvent(eventRegisterId); } } }
async Task ServerMainLoop(CancellationToken mainLoopCancel) { if (Once.IsFirstCall() == false) { throw new ApplicationException("You cannot reuse the object."); } using (var sessions = new GroupManager <ulong, SessionData>( onNewGroup: (key, state) => { Dbg.Where($"New session: {key}"); return(new SessionData()); }, onDeleteGroup: (key, ctx, state) => { Dbg.Where($"Delete session: {key}"); })) { var listener = System.CreateListener(new TcpListenParam(async(lx, sock) => { Con.WriteLine($"Connected {sock.Info.Tcp.RemoteIPAddress}:{sock.Info.Tcp.RemotePort} -> {sock.Info.Tcp.LocalIPAddress}:{sock.Info.Tcp.LocalPort}"); var app = sock.GetNetAppProtocolStub(); var st = app.GetStream(); var attachHandle = app.AttachHandle; attachHandle.SetStreamReceiveTimeout(RecvTimeout); await st.SendAsync("TrafficServer\r\n\0"._GetBytes_Ascii()); ReadOnlyMemoryBuffer <byte> buf = await st.ReceiveAsync(17); Direction dir = buf.ReadBool8() ? Direction.Send : Direction.Recv; ulong sessionId = 0; long timespan = 0; try { sessionId = buf.ReadUInt64(); timespan = buf.ReadSInt64(); } catch { } long recvEndTick = FastTick64.Now + timespan; if (timespan == 0) { recvEndTick = long.MaxValue; } using (var session = sessions.Enter(sessionId)) { using (var delay = new DelayAction((int)(Math.Min(timespan * 3 + 180 * 1000, int.MaxValue)), x => app._CancelSafe(new TimeoutException()))) { if (dir == Direction.Recv) { RefInt refTmp = new RefInt(); long totalSize = 0; while (true) { var ret = await st.FastReceiveAsync(totalRecvSize: refTmp); if (ret.Count == 0) { break; } totalSize += refTmp; if (ret[0].Span[0] == (byte)'!') { break; } if (FastTick64.Now >= recvEndTick) { break; } } attachHandle.SetStreamReceiveTimeout(Timeout.Infinite); attachHandle.SetStreamSendTimeout(60 * 5 * 1000); session.Context.NoMoreData = true; while (true) { MemoryBuffer <byte> sendBuf = new MemoryBuffer <byte>(); sendBuf.WriteSInt64(totalSize); await st.SendAsync(sendBuf); await Task.Delay(100); } } else { attachHandle.SetStreamReceiveTimeout(Timeout.Infinite); attachHandle.SetStreamSendTimeout(Timeout.Infinite); while (true) { if (sessionId == 0 || session.Context.NoMoreData == false) { await st.SendAsync(SendData); } else { var recvMemory = await st.ReceiveAsync(); if (recvMemory.Length == 0) { break; } } } } } } }, "SpeedTest", this.ServerPorts)); try { Con.WriteLine("Listening."); await TaskUtil.WaitObjectsAsync(cancels : mainLoopCancel._SingleArray()); } finally { await listener._DisposeWithCleanupSafeAsync(); } } }
async Task <Result> ClientSingleConnectionAsync(Direction dir, AsyncManualResetEvent fireMeWhenReady, CancellationToken cancel) { Result ret = new Result(); using (NetPalTcpProtocolStub tcp = new NetPalTcpProtocolStub(cancel: cancel)) { await tcp.ConnectAsync(ServerIP, ServerPort, cancel, ConnectTimeout); using (ConnSock sock = new ConnSock(tcp)) { NetAppStub app = sock.GetNetAppProtocolStub(); AttachHandle attachHandle = app.AttachHandle; PipeStream st = app.GetStream(); if (dir == Direction.Recv) { app.AttachHandle.SetStreamReceiveTimeout(RecvTimeout); } try { var hello = await st.ReceiveAllAsync(16); if (hello.Span.ToArray()._GetString_Ascii().StartsWith("TrafficServer\r\n") == false) { throw new ApplicationException("Target server is not a Traffic Server."); } //throw new ApplicationException("aaaa" + dir.ToString()); fireMeWhenReady.Set(); cancel.ThrowIfCancellationRequested(); await TaskUtil.WaitObjectsAsync( manualEvents : ClientStartEvent._SingleArray(), cancels : cancel._SingleArray() ); long tickStart = FastTick64.Now; long tickEnd = tickStart + this.TimeSpan; var sendData = new MemoryBuffer <byte>(); sendData.WriteBool8(dir == Direction.Recv); sendData.WriteUInt64(SessionId); sendData.WriteSInt64(TimeSpan); await st.SendAsync(sendData); if (dir == Direction.Recv) { RefInt totalRecvSize = new RefInt(); while (true) { long now = FastTick64.Now; if (now >= tickEnd) { break; } await TaskUtil.WaitObjectsAsync( tasks : st.FastReceiveAsync(totalRecvSize : totalRecvSize)._SingleArray(), timeout : (int)(tickEnd - now), exceptions : ExceptionWhen.TaskException | ExceptionWhen.CancelException); ret.NumBytesDownload += totalRecvSize; } } else { attachHandle.SetStreamReceiveTimeout(Timeout.Infinite); while (true) { long now = FastTick64.Now; if (now >= tickEnd) { break; } /*await WebSocketHelper.WaitObjectsAsync( * tasks: st.FastSendAsync(SendData, flush: true).ToSingleArray(), * timeout: (int)(tick_end - now), * exceptions: ExceptionWhen.TaskException | ExceptionWhen.CancelException);*/ await st.FastSendAsync(SendData, flush : true); } Task recvResult = Task.Run(async() => { var recvMemory = await st.ReceiveAllAsync(8); MemoryBuffer <byte> recvMemoryBuf = recvMemory; ret.NumBytesUpload = recvMemoryBuf.ReadSInt64(); st.Disconnect(); }); Task sendSurprise = Task.Run(async() => { byte[] surprise = new byte[260]; surprise.AsSpan().Fill((byte)'!'); while (true) { await st.SendAsync(surprise); await TaskUtil.WaitObjectsAsync( manualEvents: sock.Pipe.OnDisconnectedEvent._SingleArray(), timeout: 200); } }); await WhenAll.Await(false, recvResult, sendSurprise); await recvResult; } st.Disconnect(); return(ret); } catch (Exception ex) { ExceptionQueue !.Add(ex); throw; } } } }
public async Task <Result?> RunClientAsync() { CurrentCount.Increment(); try { if (Once.IsFirstCall() == false) { throw new ApplicationException("You cannot reuse the object."); } Con.WriteLine("Client mode start"); ExceptionQueue = new ExceptionQueue(); SessionId = Util.RandUInt64(); List <Task <Result> > tasks = new List <Task <Result> >(); List <AsyncManualResetEvent> readyEvents = new List <AsyncManualResetEvent>(); using (CancelWatcher cancelWatcher = new CancelWatcher(this.Cancel)) { for (int i = 0; i < NumConnection; i++) { Direction dir; if (Mode == SpeedTestModeFlag.Download) { dir = Direction.Recv; } else if (Mode == SpeedTestModeFlag.Upload) { dir = Direction.Send; } else { dir = ((i % 2) == 0) ? Direction.Recv : Direction.Send; } AsyncManualResetEvent readyEvent = new AsyncManualResetEvent(); var t = ClientSingleConnectionAsync(dir, readyEvent, cancelWatcher.CancelToken); ExceptionQueue.RegisterWatchedTask(t); tasks.Add(t); readyEvents.Add(readyEvent); } try { using (var whenAllReady = new WhenAll(readyEvents.Select(x => x.WaitAsync()))) { await TaskUtil.WaitObjectsAsync( tasks : tasks.Append(whenAllReady.WaitMe).ToArray(), cancels : cancelWatcher.CancelToken._SingleArray(), manualEvents : ExceptionQueue.WhenExceptionAdded._SingleArray()); } Cancel.ThrowIfCancellationRequested(); ExceptionQueue.ThrowFirstExceptionIfExists(); ExceptionQueue.WhenExceptionAdded.CallbackList.AddSoftCallback(x => { cancelWatcher.Cancel(); }); using (new DelayAction(TimeSpan * 3 + 180 * 1000, x => { cancelWatcher.Cancel(); }, doNotBlockOnDispose: true)) { ClientStartEvent.Set(true); using (var whenAllCompleted = new WhenAll(tasks)) { await TaskUtil.WaitObjectsAsync( tasks : whenAllCompleted.WaitMe._SingleArray(), cancels : cancelWatcher.CancelToken._SingleArray() ); await whenAllCompleted.WaitMe; } } Result ret = new Result(); ret.Span = TimeSpan; foreach (var r in tasks.Select(x => x._GetResult())) { ret.NumBytesDownload += r.NumBytesDownload; ret.NumBytesUpload += r.NumBytesUpload; } ret.NumBytesTotal = ret.NumBytesUpload + ret.NumBytesDownload; ret.BpsUpload = (long)((double)ret.NumBytesUpload * 1000.0 * 8.0 / (double)ret.Span * 1514.0 / 1460.0); ret.BpsDownload = (long)((double)ret.NumBytesDownload * 1000.0 * 8.0 / (double)ret.Span * 1514.0 / 1460.0); ret.BpsTotal = ret.BpsUpload + ret.BpsDownload; return(ret); } catch (Exception ex) { await Task.Yield(); ExceptionQueue.Add(ex); } finally { cancelWatcher.Cancel(); try { await Task.WhenAll(tasks); } catch { } } ExceptionQueue.ThrowFirstExceptionIfExists(); } return(null); } finally { CurrentCount.Decrement(); } }
protected override async Task MainLoopImplAsync(CancellationToken cancel) { MessageListPerConversation.Clear(); cancel.ThrowIfCancellationRequested(); CancellationTokenSource realTimeTaskCancel = new CancellationTokenSource(); Task realTimeTask = RealtimeRecvLoopAsync(realTimeTaskCancel.Token); try { bool all = true; string[]? targetChannelIdList = null; while (true) { cancel.ThrowIfCancellationRequested(); ExceptionWhen reason; try { InboxMessageBox box = await ReloadInternalAsync(all, targetChannelIdList, cancel); ClearLastError(); this.InitialLoading = false; MessageBoxUpdatedCallback(box); if (this.UpdateChannelsList.Count == 0) { reason = await TaskUtil.WaitObjectsAsync( cancels : cancel._SingleArray(), events : this.UpdateChannelsEvent._SingleArray(), timeout : Util.GenRandInterval(CoresConfig.InboxSlackAdapterSettings.RefreshAllInterval)); } else { reason = ExceptionWhen.None; } } catch (Exception ex) { SetLastError(ex._GetSingleException()); ex._Debug(); reason = ExceptionWhen.TimeoutException; await cancel._WaitUntilCanceledAsync(15000); } if (reason == ExceptionWhen.TimeoutException) { all = true; targetChannelIdList = null; lock (this.UpdateChannelsListLock) { this.UpdateChannelsList.Clear(); } } else { all = false; lock (this.UpdateChannelsListLock) { targetChannelIdList = this.UpdateChannelsList.ToArray(); this.UpdateChannelsList.Clear(); } } } } finally { realTimeTaskCancel._TryCancel(); await realTimeTask._TryWaitAsync(true); } }