2014-09-18 2 views
1

Коды ниже просто записывают количество простых чисел между a и b. C# async await работают для моих кодов, но старше dispatcher способа дает нечетное result.when я нажимаю кнопку, я получил следующий результат:
70435 простых чисел между 2000000 и 2999999
67883 штрихов между 3000000 и 3999999
66330 штрихов между 4000000 и 4999999
65367 штрихи между 5000000 и 5999999
, что является неправильным с i should be <5 and begin with 1000000. Кто-то поможет объяснить здесь состояние гонки?Как избежать состояния гонки при использовании Dispatcher.BeginInvoke()?

private void _button_Click(object sender, RoutedEventArgs e) 
{ 
    //Go(); 
    Task.Run(() => Go1()); 
} 
void Go1() 
{ 
    Dispatcher.BeginInvoke(new Action(() => _button.IsEnabled = false)); 
    for (int i = 1; i < 5; i++) 
    { 
     int result = GetPrimesCount(i * 1000000, 1000000); 
     Dispatcher.BeginInvoke(new Action(() => 
     _results.Text += result + " primes between " + (i * 1000000) + 
     " and " + ((i + 1) * 1000000 - 1) + Environment.NewLine)); 

    } 
    Dispatcher.BeginInvoke(new Action(() => _button.IsEnabled = true)); 

} 
int GetPrimesCount(int start, int count) 
{ 
    return ParallelEnumerable.Range(start, count).Count(n => 
    Enumerable.Range(2, (int)Math.Sqrt(n) - 1).All(i => n % i > 0)); 
} 
+0

Где вы пользуетесь 'Dispatcher.Invoke'? Все, что я вижу, это 'Dispatcher.BeginInvoke'? –

+0

И, похоже, здесь обсуждается эта функция здесь http://stackoverflow.com/questions/12548642/where-is-the-race-condition-in-this-code-snippet-from-c-sharp-5 -0-in-a-nutshel –

+0

@ ta.speot.is thx для ссылки. – baozi

ответ

7

Это старый глюк: Лямбдами близко над переменные, не значения, поэтому i доступ нескольких обновлений, на самом деле то же самое i.

На боковой ноте я лично переписал бы код, чтобы не использовать Dispatcher. Всегда есть лучшее решение, чем Dispatcher:

private async void _button_Click(object sender, RoutedEventArgs e) 
{ 
    _button.IsEnabled = false; 
    var progress = new Progress<Tupe<int, int>>(update => 
    { 
    _results.Text += update.Item1 + " primes between " + (update.Item2 * 1000000) + 
     " and " + ((update.Item2 + 1) * 1000000 - 1) + Environment.NewLine)); 
    }); 
    await Task.Run(() => Go1(progress)); 
    _button.IsEnabled = true; 
} 
void Go1(IProgress<Tuple<int, int>> progress) 
{ 
    for (int i = 1; i < 5; i++) 
    { 
    int result = GetPrimesCount(i * 1000000, 1000000); 
    if (progress != null) 
     progress.Report(Tuple.Create(result, i)); 
    } 
} 
Смежные вопросы