当我将Visual Studio 2010配置从Debug更改为Release时,我得到一个非常奇怪的行为:
我有一个BackgroundWorker:_bg,在DoWork中我有:
iswaiting = true; _bg.ReportProgress(1,filePath); while (iswaiting) { ; } //My other part of code (EDIT: something do to with the `result` I get from the user.)
在ProgressChanged中我有一个MessageBox,在用户交互之后,iswaiting将被设置为false并且_bg DoWork程序将继续.
void _bg_ProgressChanged(object sender,ProgressChangedEventArgs e) { //my other part of code........ result = Microsoft.Windows.Controls.MessageBox.Show("Question","Title",MessageBoxButton.YesNoCancel,MessageBoxImage.Warning); iswaiting=false; log(iswaiting.toString()); }
当我从Visual Studio运行它或构建在调试模式时,所有这些都能很好地工作,但是当我将它构建到Release时,我永远不会离开while(等待)循环,虽然我可以从日志中看到iswaiting已经设置回到假.
编辑:
更好的方式是非常欢迎!
解决方法
这可能是由于线程优化造成的.为了安全地“看到”在释放模式下等待的变化,您需要一个内存屏障.
volatile bool iswaiting;
话虽如此,像这样“旋转”将完全消耗一个cpu核心.更好的方法是使用ManualResetEvent来表示您可以继续.
// Add: private ManualResetEvent allowProgress = new ManualResetEvent(false);
然后,你不会使用等待,而是:
_bg.ReportProgress(1,filePath); allowProgress.WaitOne(); // This will block until it's set
要允许此操作继续,请使用:
result = Microsoft.Windows.Controls.MessageBox.Show("Question",MessageBoxImage.Warning); allowProgress.Set();
这里的优点是,在您被阻止时不会消耗cpu,并且您不必担心自己的内存障碍.