异步素数计算

本文关键字:计算 异步 | 更新日期: 2023-09-27 18:22:13

我有以下函数来计算第n个素数(而不是我的函数):

public long FindPrimeNumber(long n)
            {
                int count = 0;
                long a = 2;
                while (count < n)
                {
                    long b = 2;
                    int prime = 1;// to check if found a prime
                    while (b * b <= a)
                    {
                        if (a % b == 0)
                        {
                            prime = 0;
                            break;
                        }
                        b++;
                    }
                    if (prime > 0)
                        count++;
                    a++;
                }
                return (--a);
            }

我想在wpf应用程序中调用这个函数,在这里输入一个数字,然后用按钮调用该函数:

private void one_Click(object sender, RoutedEventArgs e)
        {
            answer = FindPrimeNumber(Convert.ToInt64(txtprime.Text));
            MessageBox.Show(answer.ToString());
        }

这很好,但当你开始输入一百万的数字时,速度会变慢,并会阻塞UI。

因此,我想使按钮异步,这样它就不会阻塞UI。

我就是这样尝试的:

 public async Task<long> Async_FindPrimeNumber(long n)
    {
        int count = 0;
        long a = 2;
        while (count < n)
        {
            long b = 2;
            int prime = 1;// to check if found a prime
            while (b * b <= a)
            {
                if (a % b == 0)
                {
                    prime = 0;
                    break;
                }
                b++;
            }
            if (prime > 0)
                count++;
            a++;
        }
        return (--a);
    }

异步按钮:

 private async void two_Click(object sender, RoutedEventArgs e)
        {
            answer = await Async_FindPrimeNumber(Convert.ToInt64(txtprime.Text));
            MessageBox.Show(answer.ToString());
        }

但是UI仍然被阻止。如何使此方法异步?感谢

异步素数计算

正如其他人所指出的,编译器会给你一个警告,告诉你到底出了什么问题。

要将绑定CPU的工作从UI线程推送到线程池中,可以使用Task.Run。请注意,Task.Run应用于调用方法,而不是实现它们:

private async void two_Click(object sender, RoutedEventArgs e)
{
  var input = Convert.ToInt64(txtprime.Text);
  answer = await Task.Run(() => FindPrimeNumber(input));
  MessageBox.Show(answer.ToString());
}

最简单的方法是将函数的整个主体封装在Task.Run中。输入后,async功能将同步运行,直到达到第一个await

此外,在事件处理程序中,将该函数的整个主体包装在try-catch中,async void无法像普通同步代码那样向调用方传播异常。

您可以使您的方法像一样异步

   private async void button1_Click(object sender, EventArgs e)
    {
        var answer = await FindPrimeNumberAsync(Convert.ToInt64(txtprime.Text));
        MessageBox.Show(answer.ToString());
    }
    public  Task<long> FindPrimeNumberAsync(long n)
    {
      return Task.Run<long>(()=>
       {
           int count = 0;
           long a = 2;
           while (count < n)
           {
               long b = 2;
               int prime = 1;// to check if found a prime
               while (b * b <= a)
               {
                   if (a % b == 0)
                   {
                       prime = 0;
                       break;
                   }
                   b++;
               }
               if (prime > 0)
                   count++;
               a++;
           }
           return (--a);
       });
    }