异步Prime计算

时间:2015-11-17 16:42:22

标签: c# wpf asynchronous async-await

我有以下函数来计算第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仍然被阻止。如何使此方法异步? 谢谢

3 个答案:

答案 0 :(得分:4)

正如其他人所说,编译器会给你一个警告,告诉你究竟出了什么问题。

要将UI线程中的CPU绑定工作推送到线程池,您可以使用self.id = self.id + id 。请注意pack();应该用于调用方法,而不是实现方法:

Task.Run

答案 1 :(得分:0)

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

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

答案 2 :(得分:-1)

您可以使您的方法像

一样异步
   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);
       });
    }