当前位置: 首页 > 编程语言 > C#

AsyncAwaitHoldEventOccurrenceShare

时间:2023-04-11 01:37:10 C#

AsynchronousAwaitHoldEventOccurrence我对C#.NET应用程序中的异步等待有疑问。实际上,我正试图在基于Kinect的应用程序中解决这个问题,但为了帮助说明,我做了这个类似的示例:假设我们有一个名为timer1的计时器,它设置了Timer1_Tick事件。现在,我对该事件采取的唯一操作是使用当前日期时间更新UI。privatevoidTimer1_Tick(objectsender,EventArgse){txtTimerValue.Text=DateTime.Now.ToString("hh:mm:ss.FFF",CultureInfo.InvariantCulture);这很简单,我的UI每几百分钟更新一次,我有幸看到时间流逝。现在想象一下,我也想用同样的方法来计算前500个质数,如下所示:FFF",CultureInfo.InvariantCulture);列出primeNumbersList=WorkOutFirstNPrimeNumbers(500);PrintPrimeNumbersToScreen(primeNumbersList);}privateListWorkOutFirstNPrimeNumbers(intn){ListprimeNumbersList=newList();txtPrimeAnswers.Clear();int计数器=1;while(primeNumbersList.Count但未能解决我的问题。Timer1_Tick事件中的await调用似乎仍然阻塞,阻止处理程序的进一步执行。任何帮助将不胜感激-我很擅长接受正确答案:)更新:我非常感谢@sstan能够为这个问题提供一个简洁的解决方案。但是,我无法将其应用于真实的基于Kinect的情况。因为我有点担心这个问题太具体,所以我在这里发布了一个新问题:KinectFrameArrivedAsynchronous所以你想开始一个任务而不等待结果。当任务完成计算时,它应该更新UI。首先是关于异步的一些事情,等待您的回答您的UI在长时间操作期间没有响应的原因是您没有将事件处理程序声明为异步。查看结果的最简单方法是为按钮创建事件处理程序:同步-在执行期间阻止UI:privatevoidButton1_clicked(objectsender,EventArgse){ListprimeNumbersList=WorkOutFirstNPrimeNumbers(500);PrintPrimeNumbersToScreen(primeNumbersList);}异步-执行期间的UI响应:privateasyncvoidButton1_clicked(objectsender,EventArgse){ListprimeNumbersList=awaitTask.Run(()=>WorkOutFirstNPrimeNumbers(500));PrintPrimeNumbersToScreen(primeNumbersList);注意区别:注意:你的问题:Reporttimertickswhilecalculationisstillbusy问题是你的计时器比计算快。如果在先前的计算未完成时报告了新的报价,您想要什么?无论如何,开始新的计算。这会导致同时执行许多多线程计算。忽略勾号,直到没有计算忙您也可以选择只让一个任务执行计算并在完成后立即开始计算。在这种情况下,计算是连续进行的(1)启动任务,但不要等待它。privatevoidButton1_clicked(objectsender,EventArgse){Task.Run(()=>{ListprimeNumbersList=WorkOutFirstNPrimeNumbers(500);PrintPrimeNumbersToScreen(primeNumbersList);});}(2)如果任务还在忙,忽略检查:TaskprimeCalculationTask=null;privatevoidButton1_clicked(objectsender,EventArgse){if(primeCalculationTask==null||primeCalculationTask.IsCompleted){//上一个任务完成。统计一个新的Task.Run(()=>{ListprimeNumbersList=WorkOutFirstNPrimeNumbers(500);PrintPrimeNumbersToScreen(primeNumbersList);});}}(3)开始连续计算任务privatevoidStartTask(CancellationTokentoken){Task.Run(()=>{while(!token.IsCancelRequested){ListprimeNumbersList=WorkOutFirstNPrimeNumbers(500);PrintPrimeNumbersToScreen(primeNumbersList);}})}可能不是最好的解决方案,但它会起作用。您可以创建2个独立的计时器。您的第一个计时器的Tick事件处理程序只需要处理您的txtTimerValue文本框。它可以保持原来的方式:}对于第二个定时器Tick事件处理器,定义Tick事件处理器如下:privateasyncvoidTimer2_Tick(objectsender,EventArgse){timer2.Stop();//这是必需的,因此计时器在等待此事件时停止引发Tick事件。txtPrimeAnswers.Text=awaitTask.Run(()=>{ListprimeNumbersList=WorkOutFirstNPrimeNumbers(500);returnConvertPrimeNumbersToString(primeNumbersList);});timer2.开始();//好的,现在我们可以继续滴答了。}privatestringConvertPrimeNumbersToString(ListprimeNumbersList){varprimeNumberString=newStringBuilder();foreach(intprimeNumberinprimeNumbersList){primeNumberString.AppendFormat("值{0}是素数rn",primeNumber);}返回primeNumberString()String.To;}//你的其余方法保持不变......你会注意到我将PrintPrimeNumbersToScreen()方法更改为ConvertPrimeNumbersToString()(其余方法保持不变)更改的原因是您确实希望最大限度地减少UI线程上的工作。所以最好从后台线程准备字符串,然后在UI线程上对txtPrimeAnswers文本框进行简单的赋值。编辑:与单个计时器一起使用的另一种选择这是另一个想法,但带有计时器。这里的想法是您的Tickeven处理程序将继续定期执行并每次更新您的计时器值文本框。但是,如果素数计算已经在后台进行,事件处理程序将跳过该部分。否则,它会开始素数计算并在完成后更新文本框。//仅从UI线程读取/写入的全局变量,因此不需要锁定。privateboolisCalculatingPrimeNumbers=false;privateasyncvoidTimer1_Tick(objectsender,EventArgse){txtTimerValue.Text=DateTime.Now.ToString("hh:mm:ss.FFF",CultureInfo.InvariantCulture);如果(!this.isCalculatingPrimeNumbers){this.isCalculatingPrimeNumbers=true;尝试{txtPrimeAnswers.Text=awaitTask.Run(()=>{ListprimeNumbersList=WorkOutFirstNPrimeNumbers(500);returnConvertPrimeNumbersToString(primeNumbersList);});}最后{this.isCalculatingPrimeNumbers=false;}}}privatestringConvertPrimeNumbersToString(ListprimeNumbersList){varprimeNumberString=newStringBuilder();foreach(intprimeNumberinprimeNumbersList){primeNumberString.AppendFormat("值{0}是素数rn",primeNumber);}返回primeNumberString.ToString();}//你的其余方法保持不变......tiveFramework(Rx)-NuGet“Rx-WinForms”或“Rx-WPF”-是更好的方法下面是Windows窗体解决方案所需的代码:privatevoidForm1_Load(objectsender,EventArgse){Observable.Interval(TimeSpan.FromSeconds(0.2)).Select(x=>DateTime.Now.ToString("hh:mm:ss.FFF",CultureInfo.InvariantCulture)).ObserveOn(this).Subscribe(x=>txtTimerValue.Text=x);txtPrimeAnswers.Text="";可观察的.Interval(TimeSpan.FromSeconds(0.2)).Select(n=>(int)n+1).Where(n=>DetermineIfPrime(n))。Select(n=>String.Format("Thevalue{0}isprimern",n)).Take(500).ObserveOn(this).Subscribe(x=>txtPrimeAnswers.Text+=x);}就是这样。很简单。这一切都发生在后台线程上,然后被编组回UI。以上内容应该是不言自明的,但如果您需要进一步解释,请说出来。以上就是C#学习教程:异步等待保持事件发生的全部内容。如果对你有用,需要进一步了解C#学习教程,希望大家多多关注。本文收集自网络,不代表立场。如涉及侵权,请点击右边联系管理员删除。如需转载请注明出处: