public void GlobalLockTest() { GlobalLock k = new GlobalLock("test_lock1"); Event startEvent = new Event(true); Event event2 = new Event(true); Event event3 = new Event(true); RefBool fail = new RefBool(); var thread1 = ThreadObj.Start(x => { try { startEvent.Wait(); using (k.Lock()) { event2.Set(); if (event3.Wait(100)) { fail.Set(true); } } } catch { fail.Set(true); } }); var thread2 = ThreadObj.Start(x => { try { startEvent.Wait(); event2.Wait(); using (k.Lock()) { event3.Set(); } } catch { fail.Set(true); } }); startEvent.Set(); Assert.True(thread1.WaitForEnd(5000)); Assert.True(thread2.WaitForEnd(5000)); Assert.False(fail.Value); }
// ランダムに配列した各テストを 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(); await 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); } }
public void SingleInstanceTest() { Event startEvent = new Event(true); RefBool fail = new RefBool(); Event event2 = new Event(true); Event event3 = new Event(true); Event event4 = new Event(true); Event event5 = new Event(true); Event event6 = new Event(true); var thread1 = ThreadObj.Start(x => { try { startEvent.Wait(); using (var si2 = new SingleInstance("si_test")) { event2.Set(); event3.Wait(); } event4.Set(); event5.Wait(); var si = SingleInstance.TryGet("si_test"); if (si != null) { fail.Set(true); } event6.Set(); } catch { fail.Set(true); } }); var thread2 = ThreadObj.Start(x => { try { startEvent.Wait(); event2.Wait(); var si = SingleInstance.TryGet("si_test"); if (si != null) { fail.Set(true); } event3.Set(); event4.Wait(); si = SingleInstance.TryGet("si_test"); if (si == null) { fail.Set(true); } event5.Set(); event6.Wait(); si._DisposeSafe(); } catch { fail.Set(true); } }); startEvent.Set(); Assert.True(thread1.WaitForEnd(5000)); Assert.True(thread2.WaitForEnd(5000)); Assert.False(fail.Value); }