下面的代码只记录a和b之间的素数.c#async await适用于我的代码但旧dispatcher方法给出了奇怪的结果.当我点击按钮时,我得到以下结果:
704,500素数在2000000和2999999
之间67883素数在3000000和3999999
之间66330素数在4000000和4999999
之间65367素数在5000000和5999999之间
这是错的i should be <5 and begin with 1000000.有人帮忙解释这里的竞争状况吗?
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));
}
Run Code Online (Sandbox Code Playgroud)
这是一个古老的问题:lambdas关闭变量,而不是值,因此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));
}
}
Run Code Online (Sandbox Code Playgroud)