- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我对 C# .NET 应用程序中的 async\await 有疑问。我实际上是在尝试在基于 Kinect 的应用程序中解决这个问题,但为了帮助说明,我制作了这个类似的示例:
假设我们有一个定时器,称为 timer1,它设置了一个 Timer1_Tick 事件。现在,我对该事件采取的唯一操作是使用当前日期时间更新 UI。
private void Timer1_Tick(object sender, EventArgs e)
{
txtTimerValue.Text = DateTime.Now.ToString("hh:mm:ss.FFF", CultureInfo.InvariantCulture);
}
这很简单,我的 UI 每百分之几秒更新一次,我可以愉快地看着时间流逝。
现在假设我还想用同样的方法计算前 500 个质数:
private void Timer1_Tick(object sender, EventArgs e)
{
txtTimerValue.Text = DateTime.Now.ToString("hh:mm:ss.FFF", CultureInfo.InvariantCulture);
List<int> primeNumbersList = WorkOutFirstNPrimeNumbers(500);
PrintPrimeNumbersToScreen(primeNumbersList);
}
private List<int> WorkOutFirstNPrimeNumbers(int n)
{
List<int> primeNumbersList = new List<int>();
txtPrimeAnswers.Clear();
int counter = 1;
while (primeNumbersList.Count < n)
{
if (DetermineIfPrime(counter))
{
primeNumbersList.Add(counter);
}
counter++;
}
return primeNumbersList;
}
private bool DetermineIfPrime(int n)
{
for (int i = 2; i < n; i++)
{
if (n % i == 0)
{
return false;
}
}
return true;
}
private void PrintPrimeNumbersToScreen(List<int> primeNumbersList)
{
foreach (int primeNumber in primeNumbersList)
{
txtPrimeAnswers.Text += String.Format("The value {0} is prime \r\n", primeNumber);
}
}
这是我遇到问题的时候。计算质数的密集方法会阻止事件处理程序运行 - 因此我的计时器文本框现在仅每 30 秒左右更新一次。
我的问题是,如何在遵守以下规则的同时解决这个问题:
我尝试用 async/await 做一些事情并让我的质数计算函数返回一个 Task> 但没能解决我的问题。 Timer1_Tick 事件中的 await 调用似乎仍然阻塞,阻止处理程序的进一步执行。
任何帮助将不胜感激 - 我非常擅长接受正确答案:)
更新:我非常感谢@sstan 能够为这个问题提供一个巧妙的解决方案。但是,我无法将其应用于我真实的基于 Kinect 的情况。由于我有点担心这个问题过于具体,因此我已将后续问题作为新问题发布在这里:Kinect Frame Arrived Asynchronous
最佳答案
可能不是最好的解决方案,但它会起作用。您可以创建 2 个独立的计时器。您的第一个计时器的 Tick
事件处理程序只需要处理您的 txtTimerValue
文本框。它可以保持原来的样子:
private void Timer1_Tick(object sender, EventArgs e)
{
txtTimerValue.Text = DateTime.Now.ToString("hh:mm:ss.FFF", CultureInfo.InvariantCulture);
}
对于您的第二个计时器的 Tick
事件处理程序,定义 Tick
事件处理程序如下:
private async void Timer2_Tick(object sender, EventArgs e)
{
timer2.Stop(); // this is needed so the timer stops raising Tick events while this one is being awaited.
txtPrimeAnswers.Text = await Task.Run(() => {
List<int> primeNumbersList = WorkOutFirstNPrimeNumbers(500);
return ConvertPrimeNumbersToString(primeNumbersList);
});
timer2.Start(); // ok, now we can keep ticking.
}
private string ConvertPrimeNumbersToString(List<int> primeNumbersList)
{
var primeNumberString = new StringBuilder();
foreach (int primeNumber in primeNumbersList)
{
primeNumberString.AppendFormat("The value {0} is prime \r\n", primeNumber);
}
return primeNumberString.ToString();
}
// the rest of your methods stay the same...
您会注意到我将您的 PrintPrimeNumbersToScreen()
方法更改为 ConvertPrimeNumbersToString()
(其余部分保持不变)。更改的原因是您确实希望最大限度地减少在 UI 线程上完成的工作量。所以最好从后台线程准备字符串,然后在 UI 线程上对 txtPrimeAnswers
文本框做一个简单的赋值。
编辑:另一种可以与单个计时器一起使用的替代方法
这是另一个想法,但只有一个计时器。这里的想法是您的 Tick
偶数处理程序将保持定期执行并每次更新您的计时器值文本框。但是,如果素数计算已经在后台进行,事件处理程序将跳过该部分。否则,它将开始素数计算并在完成后更新文本框。
// global variable that is only read/written from UI thread, so no locking is necessary.
private bool isCalculatingPrimeNumbers = false;
private async void Timer1_Tick(object sender, EventArgs e)
{
txtTimerValue.Text = DateTime.Now.ToString("hh:mm:ss.FFF", CultureInfo.InvariantCulture);
if (!this.isCalculatingPrimeNumbers)
{
this.isCalculatingPrimeNumbers = true;
try
{
txtPrimeAnswers.Text = await Task.Run(() => {
List<int> primeNumbersList = WorkOutFirstNPrimeNumbers(500);
return ConvertPrimeNumbersToString(primeNumbersList);
});
}
finally
{
this.isCalculatingPrimeNumbers = false;
}
}
}
private string ConvertPrimeNumbersToString(List<int> primeNumbersList)
{
var primeNumberString = new StringBuilder();
foreach (int primeNumber in primeNumbersList)
{
primeNumberString.AppendFormat("The value {0} is prime \r\n", primeNumber);
}
return primeNumberString.ToString();
}
// the rest of your methods stay the same...
关于c# - 异步等待以保持事件触发,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32035816/
我试图让脚本暂停大约 1 秒,然后继续执行脚本,但我似乎无法弄清楚如何做。这是我的代码: function hello() { alert("Hi!") //I need about a 1
wait() 和 wait(timeout) 之间有什么区别。无论如何 wait() 需要等待通知调用,但为什么我们有 wait(timeout)? 那么 sleep(timeout) 和 wait(
我需要做什么: 我有一个带有文件输入和隐藏文本输入的上传表单。用户上传图像,图像被操作,然后发送到远程服务器进行处理,这需要几秒钟,然后远程服务器将最终的图像发送回家庭服务器,并保存在新文件夹中。 J
大家好,我正在使用 Visual C++ 2010,尝试使用 Winsock 编写服务器/客户端应用程序...我不确定为什么,但有时服务器会在 listen() 函数处等待,有时会在 accept 处
任务描述 我为我的 Angular 应用程序实现了 CRSF 保护。服务器检查 crsf token 是否位于请求的 header “X-CSRF-TOKEN”中。如果不是,它会发送一个 HTTP 响
我想做这个例子https://stackoverflow.com/a/33585993/1973680同步。 这是正确的实现方式吗? let times= async (n,f)=>{
我如何将 while 循环延迟到 1 秒间隔,而不会将其运行的整个代码/计算机的速度减慢到一秒延迟(只是一个小循环)。 最佳答案 Thread.sleep(1000); // do nothing f
我知道这是一个重复的问题。但是我无法通过解释来理解。我想用一个很好的例子来清楚地理解它。任何人都可以帮忙吗。 “为什么我们从同步上下文中调用 wait()、notify() 方法”。 最佳答案 当我们
我有一个 click 事件,该事件是第一次从另一个地方自动触发的。我的问题是它运行得太快,因为所需的变量仍在由 Flash 和 Web 服务定义。所以现在我有: (function ($) {
我有如下功能 function async populateInventories(custID){ this.inventories = await this.inventoryServic
我一直对“然后”不被等待的行为感到困扰,我明白其原因。然而,我仍然需要绕过它。这是我的用例。 doWork(family) { return doWork1(family)
我想我理解异步背后的想法,返回一个Future,但是我不清楚异步在一个非常基本的层面上如何表现。据我了解,它不会自动在程序中创建异步行为。例如: import 'dart:async'; main()
我正在制作一个使用异步的Flutter应用程序,但它的工作方式不像我对它的了解。所以我对异步和在 Dart 中等待有一些疑问。这是一个例子: Future someFunction() async {
我在 main.tf 中创建资源组和 vNet,并在同一文件中引用模块。问题是,模块无法从模块访问这些资源。相关代码(删除了大部分代码,只留下相关部分): main.tf: module "worke
我的代码的问题是,当代码第一次运行时,我试图获取的 dom 元素并不总是存在,如果它不存在,那么永远不会做出 promise 。 我是否可以等到 promise 做出后再尝试实现它? 我希望我的最后一
所以,过去几天我一直在研究这段代码,并尝试实现回调/等待/任何需要的东西,但没有成功。 问题是,我如何等待响应,直到我得到两个函数的回调? (以及我将如何实现) 简而言之,我想做的是: POST 发生
谁能帮我理解这一点吗? 如果我们有一个类: public class Sample{ public synchronized method1(){ //Line1 .... wait();
这是我编写的代码,用于测试 wait() 和 notify() 的工作。现在我有很多疑问。 class A extends Thread { public void run() { try
我有以下代码由于语法错误而无法运行(在异步函数外等待) 如何使用 await 定义变量并将其导出? 当我这样定义一个变量并从其他文件导入它时,该变量是只创建一次(第一次读取文件时?)还是每次导入时都创
一个简单的线程程序,其中写入器将内容放入堆栈,读取器从堆栈中弹出。 java.util.Stack; import java.util.concurrent.ExecutorService; impo
我是一名优秀的程序员,十分优秀!