2014-09-18 1 views
1

Les codes ci-dessous enregistrent simplement le nombre de nombres premiers entre a et b. Le C# async await travaille pour mes codes mais la façon dont dispatcher donne plus result.when bizarre je clique sur le bouton, j'ai obtenu le résultat suivant:
70435 nombres premiers entre 2.000.000 et 2.999.999
67883 nombres premiers entre 3.000.000 et 3.999.999
66330 nombres premiers entre 4000000 et 4999999
65367 amorce entre 5000000 et 5999999
ce qui est faux depuis i should be <5 and begin with 1000000. Quelqu'un aide à expliquer la condition de la course ici?Comment éviter une condition de concurrence lors de l'utilisation de 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

Où utilisez-vous 'Dispatcher.Invoke'? Tout ce que je vois est 'Dispatcher.BeginInvoke'? –

+0

Et il semble y avoir une discussion sur cette fonction ici http://stackoverflow.com/questions/12548642/where-is-the-race-condition-in-this-code-snippet-from-c-sharp-5 -0-dans-un-nutshel –

+0

@ ta.speot.is thx pour le lien. – baozi

Répondre

7

Ceci est un vieux Gotcha: lambdas près des variables plus , non valeurs, de sorte que le i accessible par les mises à jour multiples est en fait le même i. D'un côté, je réécrirais personnellement le code pour ne pas utiliser Dispatcher. Il y a toujours une meilleure solution que 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)); 
    } 
} 
Questions connexes