The difference between release and debugging?

I get very strange behavior when I change the configuration of Visual Studio 2010 to Debug to Release:

I have BackgroundWorker : _bg , in DoWork I have:

  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.) 

in ProgressChanged I have a MessageBox , and after interacting with the iswaiting user, iswaiting will be set to false, and the _bg DoWork program will continue.

  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()); } 

All this works very well when I run it from Visual Studio or create it in debug mode, but when I create it for Release, I never while(iswaiting) , although I see the iswaiting log iswaiting already set to false .

EDIT

The best way to do this is more than nice!

+6
source share
2 answers

This is probably due to stream optimization. To safely “see” a change in iswaiting in release mode, you need a protective memory barrier.

The easiest way to “fix” this would mean iswaiting as volatile :

 volatile bool iswaiting; 

Speaking of this, “rotation” like this will completely absorb one CPU core. It would be much better to use ManualResetEvent to signal that you can continue.

 // Add: private ManualResetEvent allowProgress = new ManualResetEvent(false); 

Then, instead of using iswaiting, you should:

 _bg.ReportProgress(1, filePath); allowProgress.WaitOne(); // This will block until it set 

To continue, use:

  result = Microsoft.Windows.Controls.MessageBox.Show("Question" ,"Title", MessageBoxButton.YesNoCancel, MessageBoxImage.Warning); allowProgress.Set(); 

The advantage is that you will not use the processor during the lock, and you do not need to worry about the memory barriers themselves.

+6
source

So your problem is that you are using a boolean field and you have not marked it as volatile . Because of this, some optimizations (often applied only in release mode) can cause both threads to access a copy of a field that is local to their thread (for example, in the cache of their processor core).

However, labeling a volatile field is actually not a good idea. You have a more fundamental problem in that you are performing a spinway, which is almost always a bad idea. You should use a method that actually pauses the thread until it continues. One way is to use ManualResetEvent or Semaphore .

Looking at your code, you expect the user to miss a window with a message about an event with a changed course. I would say that instead of having this in an event with a change in progress, you should simply include it in the actual “do the job” event. It is advisable that the doWork method does not take care of an event with a change in progress after its launch.

+5
source

Source: https://habr.com/ru/post/927962/


All Articles