在多线程UI程序中获取System.ArgumentOutOfRangeException

时间:2015-01-25 20:45:25

标签: c# multithreading

我正在研究书籍C# 5.0 in a Nutshell中的一个例子。基本上,该例子的作用是异步计算指定范围内的素数并更新UI。当我从控制台运行代码时,它运行正常,输出如下: Console Output

然而,当我从GUI运行代码时,我在控制台上收到错误以下错误(因为项目是控制台应用程序):

  

未处理的异常:System.ArgumentOutOfRangeException:已指定   参数超出了有效值的范围。参数名称:计数
  在System.Linq.Enumerable.Range(Int32 start,Int32 count)at   Multithreading.TestUi.b__8(Int32 n)in   TestUI.cs:第38行

那么,我错过了什么?我该如何解决这个问题?

以下是生成错误的代码:

using System;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;


namespace Multithreading
{
    class TestUi:Window
    {

        private Button _button = new Button{Content = "Go"};
        private TextBlock _results = new TextBlock();

        public TestUi()
        {
            var panel = new StackPanel();
            panel.Children.Add(_button);
            panel.Children.Add(_results);
            Content = panel;
            _button.Click += (sender, args) => Go();
        }

        async void Go()
        {
            _button.IsEnabled = false; //disable the button while the calculation is proceeding.
            for (int i = 0; i < 10; i++)
            {
                int result = await GetPrimeCountAsyn(i*1000000, 1000000); //asynchronously calculate the prime numbers within the range
                _results.Text += String.Format("There are {0} primes between {1} and {2}{3}", result , (i * 100000), ((i+1) * 100000 - 1), Environment.NewLine);
            }
            _button.IsEnabled = true;
        }
        Task<int> GetPrimeCountAsyn(int start, int count)
        {
            int p = Enumerable.Range(start, count).Count(
                n => Enumerable.Range(2, (int) Math.Sqrt(n) - 1).All(i => n%i > 0));
            return Task.Run(() => p);

        }
        [STAThread]
       static void Main()
        {
            Application app = new Application();;
            app.Run(new TestUi());
            Console.ReadLine();
        }
    }
}

提前致谢。

1 个答案:

答案 0 :(得分:5)

您的问题来自Enumerable.Range(2, (int)Math.Sqrt(n) - 1)n在您第一次运行时将等于0,因此您获得的Enumerable.Range(2, -1)会超出范围异常。

这与在GUI中运行无关,你从控制台到GUI发生了某种错误。在GetPrimeCountAsyn中的控制台版本中添加断点,start传递的值不是0,或者您没有Enumerable.Range(2, (int)Math.Sqrt(n) - 1)