提问者:小点点

SemaphoreSlim之间的延迟。释放()和SemaphoreSlim。等待同步


我正在测试一个涉及信号量lim的方法,以便在事件发生时发出通知。它按预期工作,但我注意到,如果我在应用程序启动的前几秒钟内使用它,在信号量释放和代码继续等待信号量之间会有很大的延迟。

主要:

            var userIntentProvider = new UserIntentProvider();

            Console.WriteLine("started");

            
            Task.Run(() =>
            {
                Console.WriteLine("starting");
                //wait for an event to be added.
                userIntentProvider.GetNextUserIntentAsync().Wait();
            });


            while (true)
            {
                var input = Console.ReadLine();
                //add the event
                userIntentProvider.AddUserIntent("bar");
            }

类:

        public void AddUserIntent(string userIntent)
        {
            NewUserIntent?.Invoke(this, userIntent);
        }


        public async Task GetNextUserIntentAsync(CancellationToken token = new CancellationToken())
        {
            var sw = new Stopwatch();
            //create signal
            var signal = new SemaphoreSlim(0, 1);

            //create event handler
            EventHandler<string> eventHandler = null;
            eventHandler = (sender, e) =>
            {
                NewUserIntent -= eventHandler;
                
                
                signal.Release(); //THE SEMAPHORE IS RELEASED AND THE STOPWATCH STARTED
                sw.Start();
            };

            //wrap in try catch to force removal of event
            try
            {
                //subscribe
                NewUserIntent += eventHandler;

                // wait for signal 
                await signal.WaitAsync();//THE SEMAPHORE IS WAITED ON AND THE STOPWATCH STOPPED
                sw.Stop();
                Console.WriteLine("done" + sw.ElapsedMilliseconds);
            }
            finally
            {
                NewUserIntent -= eventHandler;
            }
        }

Stopwatch测量Release()和waitAsync()调用之间的时间最长可达1.5s。如果我在启动应用程序后等待几秒钟,然后触发这个机制,秒表报告0ms已经过去了(更像我所期待的),是什么导致了这种延迟?


共1个答案

匿名用户

我假设getnextUserinentAsync代码正在UI线程上运行。因此,我希望await之后的任何内容都将安排在稍后的某个时间在UI线程上运行。但是在启动过程中,UI线程通常非常忙于做其他事情,因此您的延续被放在队列的末尾,可能需要等待一段时间。