private const int GameCacheDuration = 43200; // 12 hours public async Task<GameDetails[]> ParallelLoadGames(IEnumerable<int> gameIds) { GameDetails[] results; var tasks = new List<Task<GameDetails>>(); using (var throttler = new SemaphoreSlim(5)) { foreach (var gameId in gameIds) { await throttler.WaitAsync(); tasks.Add(Task<GameDetails>.Run(async () => { try { Debug.WriteLine("Loading {0}...", gameId); return await this.LoadGame(gameId, true); } finally { Debug.WriteLine("Done with {0}...", gameId); throttler.Release(); } })); } results = await Task.WhenAll(tasks); } return results; }
public void DeclareAndUseIt() { var channel = this.Connection.CreateChannel(); var exchange = channel.DeclareExchange("my6exchange", new ExchangeOptions() { // using default options = ephemeral ExchangeType = RabbitExchangeType.Fanout }); var queue1 = exchange.DeclareQueue("q1", new QueueOptions()); var queue2 = exchange.DeclareQueue("q2", new QueueOptions()); var wait = new SemaphoreSlim(2, 2); var receivedCount = 0; queue1.Consume(new Action<MessageEnvelope<MyDumbMessage>>(env => { wait.Release(); Interlocked.Increment(ref receivedCount); }), new ConsumerOptions()); queue2.Consume(new Action<MessageEnvelope<MyDumbMessage>>(env => { wait.Release(); Interlocked.Increment(ref receivedCount); }), new ConsumerOptions()); exchange.Send(new MyDumbMessage()); // message will be dropped wait.Wait(TimeSpan.FromSeconds(2.0)); receivedCount.Should().Be(2); }
// TODO: // Hardcode a time out value for cancellation token. // For some time consuming operations, this time out needs to be tuned. public static Task BatchProcess <T>(IList <T> source, Func <T, Task> f, int max) { var initial = (max >> 1); var s = new System.Threading.SemaphoreSlim(initial, max); _ = Task.Run(async() => { for (int i = initial; i < max; i++) { await Task.Delay(100); s.Release(); } }); return(Task.WhenAll(from item in source select Task.Run(async() => { await s.WaitAsync(); try { await f(item); } catch (Exception e) { Log.Warning($"see exception in {f.Method.Name}: {e.Message}"); } finally { s.Release(); } }))); }
internal async Task Update(IEnumerable <string> streams, Func <Task <Metadata> > fetchHandler) { await Semaphore.WaitAsync(); var newMetadata = await fetchHandler(); // Updates all streams if (!streams.Any()) { MetadataData = newMetadata; } // Updates only specified streams else { var updatedStreams = MetadataData.Streams; // Removes streams from the cache that are not found in the cluster foreach (var stream in streams.Where(s => !newMetadata.HasStreamInfo(s))) { updatedStreams = updatedStreams.Remove(stream); } // Update the stream info for existing streams foreach (var stream in streams.Where(s => newMetadata.HasStreamInfo(s))) { updatedStreams = updatedStreams.SetItem(stream, newMetadata.Streams[stream]); } MetadataData = newMetadata with { Streams = updatedStreams }; } Semaphore.Release(); }
public void AsyncLockShouldAllowOnlyOneThread() { var block = new SemaphoreSlim(0, 2); var count = 0; var alock = new AsyncLock(); var firstCall = Task.Factory.StartNew(async () => { using (await alock.LockAsync()) { Interlocked.Increment(ref count); block.Wait(); } block.Wait();//keep this thread busy }); TaskTest.WaitFor(() => count > 0); alock.LockAsync().ContinueWith(t => Interlocked.Increment(ref count)); Assert.That(count, Is.EqualTo(1), "Only one task should have gotten past lock."); Assert.That(firstCall.IsCompleted, Is.False, "Task should still be running."); block.Release(); TaskTest.WaitFor(() => count > 1); Assert.That(count, Is.EqualTo(2), "Second call should get past lock."); Assert.That(firstCall.IsCompleted, Is.False, "First call should still be busy."); block.Release(); }
public static Task <TOut[]> BatchProcess <T, TOut>(IList <T> source, Func <T, Task <TOut> > f, int max) { var initial = (max >> 1); var s = new System.Threading.SemaphoreSlim(initial, max); _ = Task.Run(async() => { for (int i = initial; i < max; i++) { await Task.Delay(100); s.Release(); } }); return(Task.WhenAll(from item in source select Task.Run(async() => { TOut ret = default; var retry = 0; var maxRetry = 5; while (retry < maxRetry) { try { using (var cancellationTokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(60))) { await s.WaitAsync(cancellationTokenSource.Token); try { ret = await f(item); break; } catch (System.OperationCanceledException e) { Log.Warning($"see cancellation in {f.Method.Name}: {e.Message}"); } finally { s.Release(); } } } catch (System.OperationCanceledException) { Log.Warning($"Waiting too long time to obtain the semaphore: current: {s.CurrentCount}, max: {max}"); } var rand = new Random(); var randomDelay = TimeSpan.FromMilliseconds(rand.Next(1, 500)); await Task.Delay(randomDelay); retry++; } if (retry == maxRetry) { Log.Error($"The operation {f.Method.Name} was canceled because of reaching max retry {maxRetry}"); } return ret; }))); }
public async Task <object> RoundtripMethodCallAsync(string connectionId, string methodName, MethodRequestAndResponse requestAndResponse) { Console.WriteLine("RoundtripMethodCallAsync received for {0} and methodName {1}", connectionId, methodName); Console.WriteLine(JsonConvert.SerializeObject(requestAndResponse)); var client = objectMap[connectionId]; var mutex = new System.Threading.SemaphoreSlim(1); await mutex.WaitAsync().ConfigureAwait(false); // Grab the mutex. The handler will release it later MethodCallback callback = async(methodRequest, userContext) => { Console.WriteLine("Method invocation received"); object request = JsonConvert.DeserializeObject(methodRequest.DataAsJson); string received = JsonConvert.SerializeObject(new JRaw(request)); string expected = ((Newtonsoft.Json.Linq.JToken)requestAndResponse.RequestPayload)["payload"].ToString(); Console.WriteLine("request expected: " + expected); Console.WriteLine("request received: " + received); if (expected != received) { Console.WriteLine("request did not match expectations"); Console.WriteLine("Releasing the method mutex"); mutex.Release(); return(new MethodResponse(500)); } else { int status = 200; if (requestAndResponse.StatusCode != null) { status = (int)requestAndResponse.StatusCode; } byte[] responseBytes = GlueUtils.ObjectToBytes(requestAndResponse.ResponsePayload); Console.WriteLine("Releasing the method mutex"); mutex.Release(); Console.WriteLine("Returning the result"); return(new MethodResponse(responseBytes, status)); } }; Console.WriteLine("Setting the handler"); await client.SetMethodHandlerAsync(methodName, callback, null).ConfigureAwait(false); Console.WriteLine("Waiting on the method mutex"); await mutex.WaitAsync().ConfigureAwait(false); Console.WriteLine("Method mutex released. Waiting for a tiny bit."); // Otherwise, the connection might close before the response is actually sent await Task.Delay(100).ConfigureAwait(false); Console.WriteLine("Nulling the handler"); await client.SetMethodHandlerAsync(methodName, null, null).ConfigureAwait(false); Console.WriteLine("RoundtripMethodCallAsync is complete"); return(new object()); }
public virtual void RegisterListener(ListenerBase listener) { semaphoreSlim.Wait(); if (!_listeners.Contains(listener)) { listener.Engine = this; _listeners.Add(listener); listener.DumpEnabled = DumpEnabled; InternalTrace(Entry.CreateInfo(string.Format("Listener '{0}' registered", listener.Name))); } semaphoreSlim.Release(); }
public async Task SemaphoreSlimLock() { var _lock = new SemaphoreSlim( 1 ); await _lock.WaitAsync(); _lock.Release(); var start = Stopwatch.GetTimestamp(); for( var i = 0; i < Iterations; i++ ) { await _lock.WaitAsync(); _lock.Release(); i--; i++; } ReportTime( start ); }
static void Main(string[] args) { Console.Write("request count(8 recommanded): "); var requestCount = int.Parse(Console.ReadLine()); ServicePointManager.DefaultConnectionLimit = 10000; var alert = new AlertInSecond(); var ss = new SemaphoreSlim(requestCount, requestCount); while (true) { ss.Wait(); Task.Run(OneRequest).ContinueWith(t => { if (t.Status == TaskStatus.Faulted) { alert.AddOneFail(); } else { var response = t.Result; if (response.StatusCode == HttpStatusCode.OK) { alert.AddOneSuccess(); } else { alert.AddOneFail(); } } ss.Release(); }); } }
private async Task TestCancelWaitAsyncInternal() { var r = new Random(); var s = new SemaphoreSlim(1); await Task.WhenAll(Enumerable.Range(0, 100).Select(async i => { var ct = CancellationToken.None; if ((i % 5) == 0) { var cts = new CancellationTokenSource(); var t = Task.Delay(1).ContinueWith(_ => cts.Cancel()); ct = cts.Token; } try { await s.WaitAsync(ct); await Delay(r, ct).ConfigureAwait(false); } catch (TestException) { } catch (OperationCanceledException) { } finally { s.Release(); } })); }
public void TryDequeue_IfMustWaitForItem_ThenProvidesItAndReturnsTrue() { DoTest((q, cts) => { using (var willProvideItemAfterSleep = new SemaphoreSlim(0)) { var tasks = new Task[] { new Task(() => { string item; willProvideItemAfterSleep.Wait(); Assert.IsTrue(q.TryDequeue(out item, cts.Token)); Assert.AreEqual("7", item); }), new Task(() => { willProvideItemAfterSleep.Release(); Thread.Sleep(500); q.Enqueue(7); }) }; Parallel.ForEach<Task>(tasks, T => T.Start()); Task.WaitAll(tasks); } }); }
public static async Task<HttpResponseMessage> GetWithRetryAsync(this HttpClient client, string url, SemaphoreSlim semaphore, params int[] retryDelay) { if (retryDelay.Any(delay => delay <= 0)) { throw new ArgumentException("Delay should be greate than 0.", nameof(retryDelay)); } await semaphore.WaitAsync(); try { int retryCount = 0; while (true) { try { return await client.GetAsync(url, HttpCompletionOption.ResponseHeadersRead); } catch (TaskCanceledException) { if (retryCount >= retryDelay.Length) { throw; } } await Task.Delay(retryDelay[retryCount]); retryCount++; } } finally { semaphore.Release(); } }
public static async Task <T> DeserializeAsync <T>(Windows.Storage.StorageFile f, System.Threading.SemaphoreSlim semaphore) where T : class { await semaphore.WaitAsync(); try { if (f is null) { return(null); } using var s1 = await f.OpenAsync(Windows.Storage.FileAccessMode.Read); using var s2 = s1.AsStream(); var serializer = new System.Xml.Serialization.XmlSerializer(typeof(T)); return(serializer.Deserialize(s2) as T); } catch { return(null); } finally { semaphore.Release(); } }
public void ProducerShouldReportCorrectAmountOfAsyncRequests() { var semaphore = new SemaphoreSlim(0); var routerProxy = new FakeBrokerRouter(); //block the second call returning from send message async routerProxy.BrokerConn0.ProduceResponseFunction = () => { semaphore.Wait(); return new ProduceResponse(); }; var router = routerProxy.Create(); using (var producer = new Producer(router, maximumAsyncRequests: 1) { BatchSize = 1 }) { var messages = new[] { new Message("1") }; Assert.That(producer.AsyncCount, Is.EqualTo(0)); var sendTask = producer.SendMessageAsync(BrokerRouterProxy.TestTopic, messages); TaskTest.WaitFor(() => producer.AsyncCount > 0); Assert.That(producer.AsyncCount, Is.EqualTo(1), "One async operation should be sending."); semaphore.Release(); sendTask.Wait(TimeSpan.FromMilliseconds(500)); Assert.That(sendTask.IsCompleted, Is.True, "Send task should be marked as completed."); Assert.That(producer.AsyncCount, Is.EqualTo(0), "Async should now show zero count."); } }
private async Task <(int, int)> Scrape(Func <CancellationToken, Task <int> > process, System.Threading.SemaphoreSlim complete, TimeSpan interval, CancellationToken cancellation) { var success = 0; var error = 0; var delay = interval; while (!cancellation.IsCancellationRequested) { if (await complete.WaitAsync(delay, cancellation)) { complete.Release(); break; } try { var start = DateTimeOffset.UtcNow; await process(cancellation); var elapsed = DateTimeOffset.UtcNow - start; delay = elapsed > interval ? TimeSpan.Zero : (interval - elapsed); ++success; } catch { ++error; } } return(success, error); }
// WIP, not producing useful numbers yet. Assumes one partition. public static async Task<long> Consume(string broker, string topic) { long n = 0; var topicConfig = new TopicConfig(); topicConfig["auto.offset.reset"] = "smallest"; var config = new Config() { GroupId = "benchmark-consumer", DefaultTopicConfig = topicConfig }; using (var consumer = new EventConsumer(config, broker)) { var signal = new SemaphoreSlim(0, 1); consumer.OnMessage += (obj, msg) => { n += 1; }; consumer.OnEndReached += (obj, end) => { Console.WriteLine($"End reached"); signal.Release(); }; consumer.Subscribe(new List<string>{topic}); consumer.Start(); await signal.WaitAsync(); Console.WriteLine($"Shutting down"); } return n; }
public void ExtremeDisposal() { using (var context = CreateContext()) { Assert.AreEqual(-1, context.Publisher.MySettings.MaxConnectionRetry, "For this test, we want the worst situation"); context.Publisher.Start(0); Assert.IsTrue(context.Publisher.Started); var message = new byte[] { 0, 1, 1 }; var connectionFail = new SemaphoreSlim(0); context.Model.Setup(m => m.BasicPublish(It.IsAny<string>(), It.IsAny<string>(), context.Publisher.Props, message)).Throws(new Exception("I don't want your message anymore")); context.Connection.Setup(c => c.CreateModel()).Callback(() => connectionFail.Release(1)).Throws(new Exception("And I don't want to accept your connection either")); context.Publisher.Publish("test", message); /* The way callbacks are implemented on exception throwing mocks does not garantee * that the callback is called "after" the exception is thrown. * If we wait for two, we are sure at least one has been finished ! */ Assert.IsTrue(connectionFail.Wait(1000)); Assert.IsTrue(connectionFail.Wait(1000)); context.Publisher.Dispose(); context.Publisher = null; //to avoid the double dispose of Publisher //The real test here is that eventually the Dispose method returns Assert.Pass(); } }
static void TaskMain(SemaphoreSlim semaphore) { bool isCompleted = false; while (!isCompleted) { if (semaphore.Wait(600)) { try { Console.WriteLine("Task {0} locks the semaphore", Task.CurrentId); Thread.Sleep(2000); } finally { Console.WriteLine("Task {0} releases the semaphore", Task.CurrentId); semaphore.Release(); isCompleted = true; } } else { Console.WriteLine("Timeout for task {0}; wait again", Task.CurrentId); } } }
/// <summary> /// Ensures the list. /// </summary> /// <param name="url">The URL.</param> /// <param name="file">The file.</param> /// <param name="httpClient">The HTTP client.</param> /// <param name="fileSystem">The file system.</param> /// <param name="semaphore">The semaphore.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns>Task.</returns> public static async Task EnsureList(string url, string file, IHttpClient httpClient, IFileSystem fileSystem, SemaphoreSlim semaphore, CancellationToken cancellationToken) { var fileInfo = fileSystem.GetFileInfo(file); if (!fileInfo.Exists || (DateTime.UtcNow - fileSystem.GetLastWriteTimeUtc(fileInfo)).TotalDays > 1) { await semaphore.WaitAsync(cancellationToken).ConfigureAwait(false); try { var temp = await httpClient.GetTempFile(new HttpRequestOptions { CancellationToken = cancellationToken, Progress = new Progress<double>(), Url = url }).ConfigureAwait(false); fileSystem.CreateDirectory(Path.GetDirectoryName(file)); fileSystem.CopyFile(temp, file, true); } finally { semaphore.Release(); } } }
public void Execute(IJobExecutionContext context) { var stopwatch = new Stopwatch(); stopwatch.Start(); Logger.Info("开始抓取一号店数据"); var downloadedCategories = new YhdCategoryExtractor().Extract().Result; var needProcessCategories = _CategoryArchiveService.Archive(downloadedCategories).OrderBy(c => c.ProductsUpdateTime); var taskLock = new SemaphoreSlim(initialCount: 1); var tasks = needProcessCategories.Select(async (category, index) => { await taskLock.WaitAsync(); try { var result = await ProcessCategoryAsync(category); //■◆▲●□◇△○ Logger.Info(string.Join(" ", new[]{ string.Format("{0}", index + 1), string.Format("[{0}]{1}", category.Number, category.Name), string.Format("□{0} △{1}", result.Total, result.Changed) })); } catch (Exception e) { Logger.ErrorFormat("处理分类{0}{1}失败", e, category.Name, category.Number); } finally { taskLock.Release(); } }); Task.WaitAll(tasks.ToArray()); Logger.InfoFormat("抓取一号店数据完成,用时{0:0.#}分", stopwatch.Elapsed.TotalMinutes); }
static int Main(string[] args) { SemaphoreSlim s = new SemaphoreSlim(initialCount: 1); var cts = new CancellationTokenSource(); s.Wait(); var t = s.WaitAsync(cts.Token); s.Release(); cts.Cancel(); if (t.Status != TaskStatus.Canceled && s.CurrentCount == 0) { Console.WriteLine("PASS"); return 100; } else { Console.WriteLine("FAIL"); Console.WriteLine("Expected task status to not be Canceled and s.CurrentCount == 0"); Console.WriteLine("Actual: Task: " + t.Status + "; CurrentCount: " + s.CurrentCount); return 101; } }
public async Task<TokenPair> Authorize(string clientId, string clientSecret, IEnumerable<string> scopes) { string uri = string.Format("/LoginPage.xaml?authEndpoint={0}&clientId={1}&scope={2}", authEndpoint, clientId, string.Join(" ", scopes)); SemaphoreSlim semaphore = new SemaphoreSlim(0, 1); Observable.FromEvent<NavigatingCancelEventHandler, NavigatingCancelEventArgs>( h => new NavigatingCancelEventHandler(h), h => this.frame.Navigating += h, h => this.frame.Navigating -= h) .SkipWhile(h => h.EventArgs.NavigationMode != NavigationMode.Back) .Take(1) .Subscribe(e => semaphore.Release()); frame.Navigate(new Uri(uri, UriKind.Relative)); await semaphore.WaitAsync(); string authorizationCode = (string)PhoneApplicationService.Current.State["OAuth_Demo.AuthorizationCode"]; return await RequestAccessToken(authorizationCode, clientId, clientSecret); }
private static void TaskMain(SemaphoreSlim semaphore) { bool isCompleted = false; while (!isCompleted) { if (semaphore.Wait(600)) { try { WriteLine($"Task {Task.CurrentId} locks the semaphore"); Task.Delay(2000).Wait(); } finally { WriteLine($"Task {Task.CurrentId} releases the semaphore"); semaphore.Release(); isCompleted = true; } } else { WriteLine($"Timeout for task {Task.CurrentId}; wait again"); } } }
/// <inheritdoc/> public override async Task<FtpResponse> Process(FtpCommand command, CancellationToken cancellationToken) { if (Data.PassiveSocketClient != null) { await Data.PassiveSocketClient.DisconnectAsync(); Data.PassiveSocketClient.Dispose(); Data.PassiveSocketClient = null; } if (Data.TransferTypeCommandUsed != null && !string.Equals(command.Name, Data.TransferTypeCommandUsed, StringComparison.OrdinalIgnoreCase)) return new FtpResponse(500, $"Cannot use {command.Name} when {Data.TransferTypeCommandUsed} was used before."); int port; var isEpsv = string.Equals(command.Name, "EPSV", StringComparison.OrdinalIgnoreCase); if (isEpsv) { if (string.IsNullOrEmpty(command.Argument) || string.Equals(command.Argument, "ALL", StringComparison.OrdinalIgnoreCase)) { port = 0; } else { port = Convert.ToInt32(command.Argument, 10); } } else { port = 0; } Data.TransferTypeCommandUsed = command.Name; var sem = new SemaphoreSlim(0, 1); var listener = new TcpSocketListener(); listener.ConnectionReceived += (sender, args) => { Data.PassiveSocketClient = args.SocketClient; sem.Release(); }; await listener.StartListeningAsync(port); var localPort = listener.LocalPort; if (isEpsv || Server.ServerAddress.Contains(":")) { var listenerAddress = new Address(localPort); await Connection.WriteAsync(new FtpResponse(229, $"Entering Extended Passive Mode ({listenerAddress})."), cancellationToken); } else { var listenerAddress = new Address(Server.ServerAddress, localPort); await Connection.WriteAsync(new FtpResponse(227, $"Entering Passive Mode ({listenerAddress})."), cancellationToken); } await sem.WaitAsync(TimeSpan.FromSeconds(5), cancellationToken); await listener.StopListeningAsync(); listener.Dispose(); return null; }
/// <summary> /// Release the current semaphoreSlim and send a signal to others. /// </summary> public void Release() { if (IsLockOwnedFlag) { _currentObject.Release(); IsLockOwnedFlag = false; } }
public void ConcurrentSetsAndWaits__3() { var autoResSlim = new AutoResetSuperSlimLock(false); var obtainedEv = new AutoResetEvent(true); var barrier = new ManualResetEvent(false); var semaphore = new SemaphoreSlim(0, 4); int countOfObtained = 0; int countOfMissed = 0; var tasks = new List<Task>(); for (int i = 0; i < 4; i++) { var t = Task.Factory.StartNew((p) => { barrier.WaitOne(); for (int j = 0; j < 1000; j++) { if (autoResSlim.Wait()) { Interlocked.Increment(ref countOfObtained); // Console.WriteLine(countOfObtained + " _ " + p); obtainedEv.Set(); } else { Interlocked.Increment(ref countOfMissed); } } semaphore.Release(); }, i); tasks.Add(t); } var t1 = Task.Factory.StartNew(() => { barrier.Set(); for (int i = 0; i < 4000; i++) { obtainedEv.WaitOne(); autoResSlim.Set(); // Console.WriteLine("*\t" + i); } }); tasks.Add(t1); Task.WaitAll(tasks.ToArray()); for (int i = 0; i < 4; i++) semaphore.Wait(); countOfObtained.Should().Be(4000); autoResSlim.IsSet.Should().BeFalse(); }
internal void RegisterContext(HttpListenerContext context) { if (!_ctxQueue.TryAdd(context.Id, context)) { throw new InvalidOperationException("Unable to register context"); } _ctxQueueSem.Release(); }
public void CurrentCountMaxTestCase() { using (var semMax = new SemaphoreSlim(5, 5)) { semMax.Wait(); try { semMax.Release(3); Assert.Fail (); } catch (SemaphoreFullException) {} } }
static async Task Main(string[] args) { // Create the semaphore. semaphore = new System.Threading.SemaphoreSlim(0, 3); Console.WriteLine("{0} tasks can enter the semaphore.", semaphore.CurrentCount); Task[] tasks = new Task[5]; // Create and start five numbered tasks. for (int i = 0; i <= 4; i++) { tasks[i] = Task.Run(() => { // Each task begins by requesting the semaphore. Console.WriteLine("Task {0} begins and waits for the semaphore.", Task.CurrentId); semaphore.Wait(); Interlocked.Add(ref padding, 100); Console.WriteLine("Task {0} enters the semaphore.", Task.CurrentId); // The task just sleeps for 1+ seconds. Thread.Sleep(1000 + padding); Console.WriteLine("Task {0} releases the semaphore; previous count: {1}.", Task.CurrentId, semaphore.Release()); }); } // Wait for half a second, to allow all the tasks to start and block. Thread.Sleep(500); // Restore the semaphore count to its maximum value. Console.WriteLine("Main thread calls Release(3) --> "); semaphore.Release(3); Console.WriteLine(" {0} tasks can enter the semaphore.", semaphore.CurrentCount); // Main thread waits for the tasks to complete. await Task.WhenAll(tasks); Console.WriteLine("Main thread exits."); Console.ReadLine(); }
public static RowCol NextMove(Board board, IPlayer me, IPlayer opp) { // this is similar to of MyMove but with logging and multithreading var moves = new Dictionary<RowCol, int> (); var legalMoves = board.GetLegalMoves (); int count = 0; Console.WriteLine ("Starting move assessment ({0} to assess)", legalMoves.Count ()); var semaphore = new SemaphoreSlim (4); var tasks = new Task[legalMoves.Count ()]; foreach (var move in legalMoves) { var count1 = ++count; tasks[count1-1] = Task.Run (() => { semaphore.Wait(); Console.WriteLine ("{0} starting (option {1}/{2})", move, count1, legalMoves.Count ()); var b = board.Play (me, move); var isGameOver = b.IsGameOver (me); int value; if (isGameOver == GameEnd.Win) value = int.MaxValue; // if we can win, take it now! else if (isGameOver == GameEnd.Tie) value = 0; else value = OppMove (b, me, opp); moves [move] = value; Console.WriteLine ("{0} scores {1} (option {2}/{3})", move, value, count1, legalMoves.Count ()); semaphore.Release(); }); } Task.WaitAll (tasks); var bestMove = null as RowCol; int best = -1; foreach (var kvp in moves) if (kvp.Value > best) { best = kvp.Value; bestMove = kvp.Key; } if (bestMove != null) Console.WriteLine ("The best move is {0}, with a score of {1}", bestMove, best); else { Console.WriteLine ("All moves should result in losing, choosing randomly"); bestMove = legalMoves [new Random ().Next (legalMoves.Count)]; } return bestMove; }
public void Execute() { // // SemaphoreSlimのWaitメソッドにはキャンセルトークンを // 受け付けるオーバーロードが存在する。 // // CountdownEventやBarrierの場合と同じく、Waitメソッドに // キャンセルトークンを指定した場合、別の場所にてキャンセルが // 行われると、OperationCanceledExceptionが発生する。 // const int timeout = 2000; var tokenSource = new CancellationTokenSource(); var token = tokenSource.Token; using (var semaphore = new SemaphoreSlim(2)) { // // あらかじめ、セマフォの上限までWaitしておき // 後のスレッドが入れないようにしておく. // semaphore.Wait(); semaphore.Wait(); // // 3つのタスクを作成する. // 1つ目のタスク:キャンセルトークンを指定して無制限待機. // 2つ目のタスク:キャンセルトークンとタイムアウト値を指定して待機. // 3つ目のタスク:特定時間待機した後、キャンセル処理を行う. // Parallel.Invoke ( () => WaitProc1(semaphore, token), () => WaitProc2(semaphore, timeout, token), () => DoCancel(timeout, tokenSource) ); semaphore.Release(); semaphore.Release(); Output.WriteLine("CurrentCount={0}", semaphore.CurrentCount); } }
public async Task Invoke(IncomingContext context) { int currentIndex = 0; var semaphore = new SemaphoreSlim(1); Stack<Tuple<Task, TaskCompletionSource<ExceptionDispatchInfo>>> sources = new Stack<Tuple<Task, TaskCompletionSource<ExceptionDispatchInfo>>>(); while (currentIndex < executingElements.Count) { await semaphore.WaitAsync().ConfigureAwait(false); var element = executingElements[currentIndex]; currentIndex += 1; var tcs = new TaskCompletionSource<ExceptionDispatchInfo>(); var task = element.Invoke(context, () => { semaphore.Release(); return tcs.Task; }); sources.Push(Tuple.Create(task, tcs)); } ExceptionDispatchInfo exception = null; var anotherSemaphore = new SemaphoreSlim(1); var allTasks = new ConcurrentBag<Task>(); foreach (var source in sources) { await anotherSemaphore.WaitAsync().ConfigureAwait(false); if (exception != null) { context.Exceptions.Enqueue(exception); source.Item2.TrySetException(exception.SourceException); exception = null; } else { source.Item2.TrySetResult(null); } var task = source.Item1.ContinueWith(t => { if (t.Exception != null) { exception = ExceptionDispatchInfo.Capture(t.Exception.InnerException); } anotherSemaphore.Release(); }, TaskContinuationOptions.ExecuteSynchronously); allTasks.Add(task); } await Task.WhenAll(allTasks).ConfigureAwait(false); }
public void Foo(Action printFoo) { for (int i = 0; i < n; i++) { slim1.Wait(); // printFoo() outputs "foo". Do not change or remove this line. printFoo(); slim2.Release(); } }
public void Bar(Action printBar) { for (int i = 0; i < n; i++) { slim2.Wait(); // printBar() outputs "bar". Do not change or remove this line. printBar(); slim1.Release(); } }
public IList<WorkItemModel> GetWorkItemCollection() { IEnumerable<ICloudWorkItem> workItems = this.Service.ListWorkItems(OptionsModel.Instance.ListDetailLevel); using (var sem = new SemaphoreSlim(MaxJobRequestsInFlight)) { var workItemsTasks = workItems.Select( async cloudWorkItem => { if (cloudWorkItem.ExecutionInformation != null && cloudWorkItem.ExecutionInformation.RecentJob != null) { try { await sem.WaitAsync(); try { var latestJob = await cloudWorkItem.GetJobAsync(cloudWorkItem.ExecutionInformation.RecentJob.Name); return new WorkItemModel(cloudWorkItem, latestJob); } finally { sem.Release(); } } catch (BatchException be) { if (be.RequestInformation != null && be.RequestInformation.AzureError != null && be.RequestInformation.AzureError.Code == BatchErrorCodeStrings.JobNotFound) { return new WorkItemModel(cloudWorkItem); } return null; } catch (Exception) { // eat the exception for now return null; } } else { return new WorkItemModel(cloudWorkItem); } }) .ToArray(); Task.WaitAll(workItemsTasks); return workItemsTasks .Select(task => task.Result) .Where(workItemModel => workItemModel != null) .ToList(); } }
private static async Task InSemaphore(SemaphoreSlim sync, Func<Task> func) { await sync.WaitAsync(); try { await func(); } finally { sync.Release(); } }
public void Dispose_should_cancel_pending_request() { var semaphore = new SemaphoreSlim(1); semaphore.Wait(); var subject = new SemaphoreSlimRequest(semaphore, CancellationToken.None); subject.Dispose(); semaphore.Release(); subject.Task.Status.Should().Be(TaskStatus.Canceled); semaphore.CurrentCount.Should().Be(1); }
public void ConcurrentEmitsReachForEach() { var count = 100; var howOften = 1000; var source = AsyncEnumerable.Source<int>(); var evt = new ManualResetEventSlim(); var sem = new SemaphoreSlim(0); var derived = source.Select(i => i).Where(i => true); var values = new HashSet<int>(); var subscription = source.ForEach(i => { lock (values) { values.Add(i); } }); for (int i = 0; i < count; i++) { var id = i; var t = new Thread(() => { evt.Wait(); for(int x = 0; x < howOften; x++) source.Yield(id).Wait(); sem.Release(); }); t.IsBackground = true; t.Start(); } evt.Set(); for (int i = 0; i < count; i++) sem.Wait(); var arr = values.OrderBy(a => a).ToArray(); Assert.AreEqual(count, arr.Length, "not all inputs processed"); for (int i = 0; i < count; i++) { Assert.AreEqual(i, arr[i]); } }
public void WaitRelease() { using (var semaphore = new SemaphoreSlim(2, 2)) { var stopwatch = Stopwatch.StartNew(); for (var i = 0; i < Iterations; i++) { semaphore.Wait(); semaphore.Release(); } stopwatch.StopAndLog(Iterations); } }
private async Task WaitAsync(SemaphoreSlim s, CancellationTokenSource cts) { try { await s.WaitAsync(); await Task.Delay(10); cts.Cancel(); } catch (OperationCanceledException) { } finally { s.Release(); } }
public async Task ExecuteAsync(ITestPattern testPattern, IWorkerStrategy execStrategy, CancellationToken cancelToken) { SemaphoreSlim cancelSignaled = new SemaphoreSlim(0, 1); using (cancelToken.Register(() => cancelSignaled.Release())) { for (int i = 0; i < this.WorkerCount; i++) { execStrategy.SpawnWorker(testPattern, cancelToken); } await cancelSignaled.WaitAsync(); } }
public void Run(Action action) { _semaphore.Wait(); Task.Factory.StartNew(() => { try { // This task pool is used for jobs only, so the actions are guaranteed to not throw exceptions action(); } finally { _semaphore.Release(); } }); }
public async Task <EventBody> WaitForInputMessageAsync(string connectionId, string inputName) { Console.WriteLine("WaitForInputMessageAsync received for {0} with inputName {1}", connectionId, inputName); var mutex = new System.Threading.SemaphoreSlim(1); await mutex.WaitAsync().ConfigureAwait(false); // Grab the mutex. The handler will release it later byte[] bytes = null; var client = objectMap[connectionId]; MessageHandler handler = async(msg, context) => { Console.WriteLine("message received"); bytes = msg.GetBytes(); await client.SetInputMessageHandlerAsync(inputName, null, null).ConfigureAwait(false); Console.WriteLine("releasing inputMessage mutex"); mutex.Release(); return(MessageResponse.Completed); }; Console.WriteLine("Setting input handler"); await client.SetInputMessageHandlerAsync(inputName, handler, null).ConfigureAwait(false); Console.WriteLine("Waiting for inputMessage mutex to release"); await mutex.WaitAsync().ConfigureAwait(false); Console.WriteLine("mutex triggered."); string s = Encoding.UTF8.GetString(bytes); Console.WriteLine("message = {0}", s as object); object result; try { result = JsonConvert.DeserializeObject(s); } catch (JsonReaderException) { result = s; } return(new Models.EventBody { Body = result }); }
public static async Task SerializeAsync <T>(T content, Windows.Storage.StorageFolder folder, string fileName, System.Threading.SemaphoreSlim semaphore) { await semaphore.WaitAsync(); try { var f = await folder.CreateFileAsync(fileName, Windows.Storage.CreationCollisionOption.ReplaceExisting); using var s = (await f.OpenAsync(Windows.Storage.FileAccessMode.ReadWrite)).AsStream(); var serializer = new System.Xml.Serialization.XmlSerializer(typeof(T)); serializer.Serialize(s, content); } catch { } finally { semaphore.Release(); } }
private async void VideoDevice_FrameArrived(object sender, NewFrameEventArgs eventArgs) { if (SettingService.IsMirror) { eventArgs.Frame.RotateFlip(RotateFlipType.RotateNoneFlipX); } if (!await semaphore.WaitAsync(0)) { return; } try { using (Bitmap bitmap = (Bitmap)eventArgs.Frame.Clone()) { var detectedBarcode = await barcodeService.DetectBarcodeFromBitmapAsync(bitmap); if (detectedBarcode != null) { if (lastDetectedBarcodeValue != detectedBarcode.BarcodeValue) { WriteTextSafe(detectedBarcode.BarcodeValue); if (SettingService.IsSaveToCSV) { ExportCSV(detectedBarcode); } if (SettingService.IsCopyToClipboard) { CopyToClipboard(detectedBarcode); } lastDetectedBarcodeValue = detectedBarcode.BarcodeValue; } } } } finally { semaphore.Release(); } }
public void ScpToRemote(List <string> files, string dir_path, string dir, IVsOutputWindowPane outputWindowPane) { try { lock (lock_obj) { // ThreadHelper.ThrowIfNotOnUIThread(); var dte = Package.GetGlobalService(typeof(DTE)) as EnvDTE80.DTE2; dte.Windows.Item(EnvDTE.Constants.vsWindowKindOutput).Activate(); if (files.Count == 0) { outputWindowPane.OutputStringThreadSafe("No file can be copied"); return; } ConnectionInfoStore connectionInfoStore = new ConnectionInfoStore(); connectionInfoStore.Load(); if (connectionInfoStore.Connections.Count < 1) { outputWindowPane.OutputStringThreadSafe("No connection found. Add connection in [Tools] / [Options] / [Cross Platform]"); return; } outputWindowPane.OutputStringThreadSafe("Connecting...\n"); if (remoteSystem == null) { remoteSystem = new RemoteSystem((ConnectionInfo)connectionInfoStore.Connections[0]); directory = remoteSystem.FileSystem.GetDirectory(SpecialDirectory.Home); } using (var concurrencySemaphore = new System.Threading.SemaphoreSlim(8)) { int num = 0; int length = files.Count; List <Task> tasks = new List <Task>(); foreach (string file in files) { concurrencySemaphore.Wait(); var t = Task.Run(() => { string str2 = file.Substring(dir_path.Length); string remoteFileName = directory.FullPath + "/projects/" + dir + str2.Replace('\\', '/'); string remotePath = remoteFileName.Substring(0, remoteFileName.LastIndexOf('/')); try { if (File.Exists(file)) { remoteSystem.FileSystem.UploadFile(file, remoteFileName); outputWindowPane.OutputStringThreadSafe("[" + Interlocked.Increment(ref num) + "/" + length + "] " + remoteFileName + "\n"); } else { Interlocked.Increment(ref num); outputWindowPane.OutputStringThreadSafe("Skip " + file + " (file not exists)\n"); } } catch (liblinux.IO.IOException ex1) { if (ex1.Message.Contains("No such file")) { remoteSystem.FileSystem.CreateDirectories(remotePath); remoteSystem.FileSystem.UploadFile(file, remoteFileName); outputWindowPane.OutputStringThreadSafe("[" + Interlocked.Increment(ref num) + "/" + length + "] " + remoteFileName + "\n"); } else { Interlocked.Increment(ref num); outputWindowPane.OutputStringThreadSafe("Upload failed: " + file + "\n"); } } catch (Exception ex) { Interlocked.Increment(ref num); outputWindowPane.OutputStringThreadSafe("Upload failed: " + file + ", ex: " + ex.ToString() + "\n"); } finally { concurrencySemaphore.Release(); } }); tasks.Add(t); } Task.WaitAll(tasks.ToArray()); } remoteSystem.Disconnect(); remoteSystem.Dispose(); outputWindowPane.OutputStringThreadSafe("Copy to " + remoteSystem.ConnectionInfo.HostNameOrAddress + " done.\n"); // prepare for next time remoteSystem = new RemoteSystem((ConnectionInfo)connectionInfoStore.Connections[0]); directory = remoteSystem.FileSystem.GetDirectory(SpecialDirectory.Home); } } catch (Exception ex) { remoteSystem = null; throw ex; } }
//#################################################################################################################################################################### /// <summary> /// Get all releases from the GitHub repository /// </summary> /// see: https://github.com/nixxquality/GitHubUpdate public async Task GetAllGitHubReleases() { try { ErrorOccuredWhileLoadingReleases = false; ErrorMessage = string.Empty; GitHubReleases?.Clear(); if (!IsGitHubRepoAssigned) { GitHubReleases = null; return; } // example url: https://github.com/M1S2/AssemblyInfoHelper string[] urlSplitted = AssemblyInfoHelperClass.GitHubRepoUrl.Split('/'); if (urlSplitted.Length < 5) { return; } string repoOwner = urlSplitted[3]; string repoName = urlSplitted[4]; GitHubClient gitHubClient = new GitHubClient(new ProductHeaderValue("AssemblyInfoHelper-UpdateCheck")); List <Release> originalReleases = new List <Release>(await gitHubClient.Repository.Release.GetAll(repoOwner, repoName)); SemVersion currentVersion = stripInitialV(AssemblyInfoHelperClass.AssemblyVersion); SemVersion previousVersion = new SemVersion(0, 0, 0); originalReleases.Reverse(); List <GitHubRelease> tmpGitHubReleases = new List <GitHubRelease>(); foreach (Release release in originalReleases) { SemVersion releaseVersion = stripInitialV(release.TagName); tmpGitHubReleases.Add(new GitHubRelease() { Name = release.Name, ReleaseTime = release.CreatedAt.ToLocalTime(), Version = releaseVersion, ReleaseTimeType = (releaseVersion > currentVersion ? GitHubReleaseTimeTypes.NEW : (releaseVersion == currentVersion ? GitHubReleaseTimeTypes.CURRENT : GitHubReleaseTimeTypes.OLD)), ReleaseURL = release.HtmlUrl, ReleaseNotes = release.Body, ReleaseType = getReleaseTypeFromVersions(releaseVersion, previousVersion), /* Asset Names should be: * For binaries: %ProjectName%_Binaries.zip, %ProjectName%.zip, %ProjectName%_v1.0.0.zip, bin.zip * For installer: %ProjectName%_Installer.zip, Installer.zip, Setup.zip, Setup.exe */ BinAsset = release.Assets.Where(a => a.Name.ToLower().Contains("bin") || (a.Name.ToLower().StartsWith(AssemblyInfoHelperClass.AssemblyTitle.ToLower()) && !a.Name.ToLower().Contains("inst") && !a.Name.ToLower().Contains("setup"))).FirstOrDefault(), InstallerAsset = release.Assets.Where(a => a.Name.ToLower().Contains("inst") || a.Name.ToLower().Contains("setup")).FirstOrDefault() }); previousVersion = releaseVersion; } tmpGitHubReleases.Reverse(); foreach (GitHubRelease r in tmpGitHubReleases) { GitHubReleases.Add(r); } if (SemaphoreGetReleases.CurrentCount == 0) { SemaphoreGetReleases.Release(); } } catch (Exception ex) { ErrorOccuredWhileLoadingReleases = true; ErrorMessage = ex.Message + (ex.InnerException != null ? Environment.NewLine + ex.InnerException.Message : ""); if (SemaphoreGetReleases.CurrentCount == 0) { SemaphoreGetReleases.Release(); } } }
public static void RunWithController(TestHelper helper, IControllerPrx controller) { Communicator?communicator = helper.Communicator; TestHelper.Assert(communicator != null); var timeout = ITimeoutPrx.Parse(helper.GetTestProxy("timeout", 0), communicator); System.IO.TextWriter output = helper.Output; output.Write("testing connect timeout... "); output.Flush(); { Dictionary <string, string>?properties = communicator.GetProperties(); properties["Ice.ConnectTimeout"] = "100ms"; using var comm = new Communicator(properties); var to = ITimeoutPrx.Parse(helper.GetTestProxy("timeout", 0), comm); // Expect ConnectTimeoutException. controller.HoldAdapter(-1); try { to.Op(); TestHelper.Assert(false); } catch (ConnectTimeoutException) { // Expected. } controller.ResumeAdapter(); timeout.Op(); // Ensure adapter is active. } { // Expect success. controller.HoldAdapter(100); timeout.Op(); } output.WriteLine("ok"); // The sequence needs to be large enough to fill the write/recv buffers byte[] seq = new byte[2000000]; output.Write("testing connection timeout... "); output.Flush(); { // Expect TimeoutException. controller.HoldAdapter(-1); timeout.GetConnection() !.Acm = new Acm(TimeSpan.FromMilliseconds(50), AcmClose.OnInvocationAndIdle, AcmHeartbeat.Off); try { timeout.SendData(seq); TestHelper.Assert(false); } catch (ConnectionTimeoutException) { // Expected. } controller.ResumeAdapter(); timeout.Op(); // Ensure adapter is active. } { // Expect success. controller.HoldAdapter(100); try { timeout.SendData(new byte[1000000]); } catch (ConnectionTimeoutException) { TestHelper.Assert(false); } } output.WriteLine("ok"); output.Write("testing invocation timeout... "); output.Flush(); { timeout.IcePing(); // Makes sure a working connection is associated with the proxy Connection?connection = timeout.GetConnection(); try { using var timeoutTokenSource = new CancellationTokenSource(TimeSpan.FromMilliseconds(100)); timeout.SleepAsync(1000, cancel: timeoutTokenSource.Token).Wait(); TestHelper.Assert(false); } catch (AggregateException ex) when(ex.InnerException is OperationCanceledException) { } timeout.IcePing(); TestHelper.Assert(connection == timeout.GetConnection()); try { using var timeoutTokenSource = new CancellationTokenSource(TimeSpan.FromMilliseconds(1000)); timeout.SleepAsync(100, cancel: timeoutTokenSource.Token).Wait(); } catch (AggregateException ex) when(ex.InnerException is OperationCanceledException) { TestHelper.Assert(false); } TestHelper.Assert(connection == timeout.GetConnection()); } output.WriteLine("ok"); output.Write("testing close timeout... "); output.Flush(); { Dictionary <string, string> properties = communicator.GetProperties(); properties["Ice.CloseTimeout"] = "100ms"; using var comm = new Communicator(properties); var to = ITimeoutPrx.Parse(helper.GetTestProxy("timeout", 0), comm); Connection?connection = to.GetConnection(); Connection?connection2 = timeout.GetConnection(); // No close timeout TestHelper.Assert(connection != null && connection2 != null); controller.HoldAdapter(-1); // Make sure there's no ReadAsync pending _ = to.IcePingAsync(); _ = timeout.IcePingAsync(); var semaphore = new System.Threading.SemaphoreSlim(0); connection.Closed += (sender, args) => semaphore.Release(); connection.Close(ConnectionClose.Gracefully); TestHelper.Assert(semaphore.Wait(500)); connection2.Closed += (sender, args) => semaphore.Release(); connection2.Close(ConnectionClose.Gracefully); TestHelper.Assert(!semaphore.Wait(500)); controller.ResumeAdapter(); timeout.Op(); // Ensure adapter is active. } output.WriteLine("ok"); output.Write("testing invocation timeouts with collocated calls... "); output.Flush(); { communicator.SetProperty("TimeoutCollocated.AdapterId", "timeoutAdapter"); ObjectAdapter adapter = communicator.CreateObjectAdapter("TimeoutCollocated"); adapter.Activate(); ITimeoutPrx proxy = adapter.AddWithUUID(new Timeout(), ITimeoutPrx.Factory); try { using var timeoutTokenSource = new CancellationTokenSource(TimeSpan.FromMilliseconds(100)); proxy.SleepAsync(500, cancel: timeoutTokenSource.Token).Wait(); TestHelper.Assert(false); } catch (AggregateException ex) when(ex.InnerException is OperationCanceledException) { } adapter.Dispose(); } output.WriteLine("ok"); controller.Shutdown(); }
async Task <string> CutByCode(string dataInput)//the method: double(double C,double E) //count, entropy, return score { var counter = System.Threading.Interlocked.Increment(ref counter_CutByCode); try { await SemaphoreSlim_CutByCode.WaitAsync(); if (counter != System.Threading.Interlocked.Read(ref counter_CutByCode)) { return(null); } const string namespaceName = "WikiDataAnalysis", className = "FooClass", methodName = "FooMethod"; string code = "using System;" + $"namespace {namespaceName}" + "{" + $" class {className}" + " {" + $" public static double {methodName}(string S,int N,Func<string,int> C)" + " {" + $" {dataInput}" + " }" + " }" + "}"; System.Reflection.MethodInfo methodInfo; try { Trace.Indent(); Trace.WriteLine($"Compiling... code length = {code.Length}"); methodInfo = Utils.DynamicCompile.GetMethod(code, namespaceName, className, methodName, "System"); var method = new Func <string, int, Func <string, int>, double>((s, n, c) => (double)methodInfo.Invoke(null, new object[] { s, n, c })); Trace.WriteLine("Splitting..."); var maxWordLength = int.Parse(IFdata.GetField("maxWordLength")); var probRatio = double.Parse(IFdata.GetField("probRatio")); var bemsRatio = double.Parse(IFdata.GetField("bemsRatio")); StringBuilder sb_ret = new StringBuilder(); long cnt = 0; await Task.Run(() => { var mainInputs = string.IsNullOrWhiteSpace(TXBdata.Text) ? (txbDataFileContent != null ? txbDataFileContent : data) : TXBdata.Text; var inputs = mainInputs.Split(' ', '\r', '\n', '\t'); if (ss_CutByCode == null) { ss_CutByCode = new SentenceSplitter(sa); } const int maxoutputLength = 10000; bool appending = true; int progress = 0, total_progress = inputs.Length; var lastUpdateTime = DateTime.MinValue; foreach (var input in inputs) { ++progress; if ((DateTime.Now - lastUpdateTime).TotalSeconds > 0.5) { Trace.WriteLine($"Splitting... {progress}/{total_progress}"); lastUpdateTime = DateTime.Now; } var cutResult = ss_CutByCode.Split(input, maxWordLength, method, false); cnt += cutResult.Count; if (sb_ret.Length + cutResult.Sum(s => (long)s.Length) > maxoutputLength) { appending = false; } if (appending) { sb_ret.AppendLine(string.Join(" ", cutResult)); } } }); Trace.WriteLine($"{cnt} words identified."); return(sb_ret.ToString()); } catch (Exception error) { return(error.ToString()); } finally { Trace.Unindent(); } } finally { lock (SemaphoreSlim_CutByCode) SemaphoreSlim_CutByCode.Release(); } }
protected async ValueTask InitilizeAsync() { if (initilized) { await TestSemaphoreSlim.WaitAsync(); await RunBrowserAsync(); Page = await Browser.NewPageAsync(); await Page.GoToAsync("https://localhost:5001"); return; } await InitilizeSemaphoreSlim.WaitAsync(); try { if (initilized) { await TestSemaphoreSlim.WaitAsync(); await RunBrowserAsync(); Page = await Browser.NewPageAsync(); await Page.GoToAsync("https://localhost:5001"); return; } Output.WriteLine("启动服务器"); hostBuilder = Program.CreateHostBuilder(new string[0]); source = new System.Threading.CancellationTokenSource(); var host = hostBuilder.Build(); _ = host.RunAsync(source.Token); demoTesterTypes = AppDomain.CurrentDomain.GetAssemblies() .Where(x => !x.IsDynamic) .SelectMany(x => x.ExportedTypes) .Where(x => x.GetInterface(nameof(IDemoTester)) != null) .Select(x => { var testNameAttribute = x.GetCustomAttributes(false).OfType <TestNameAttribute>().FirstOrDefault(); return(new { Menu = testNameAttribute.MenuName, testNameAttribute.Name, Type = x }); }) .GroupBy(x => x.Menu) .ToDictionary(x => x.Key, x => x.ToDictionary(y => y.Name, y => y.Type)); Output.WriteLine("下载浏览器"); var fetcher = new BrowserFetcher(); if (!File.Exists(fetcher.DownloadsFolder)) { await fetcher.DownloadAsync(BrowserFetcher.DefaultRevision); } else { await Task.Delay(1000); } await TestSemaphoreSlim.WaitAsync(); await RunBrowserAsync(); Page = await Browser.NewPageAsync(); await Page.GoToAsync("https://localhost:5001"); Output.WriteLine("初始化完成"); initilized = true; } finally { InitilizeSemaphoreSlim.Release(); } }