Я использовал volatile, где я не уверен, что это необходимо. Я был уверен, что замок в моей ситуации будет излишним. Чтение этой темы (комментарий Эрика Липперта) заставляет меня беспокоиться о моем использовании волатильности: When should the volatile keyword be used in c# ?C# - Использование летучих ключевых слов против блокировки
Я использовал volatile, потому что моя переменная используется в многопоточном контексте, где эта переменная может быть доступна или изменена одновременно, но где я могу потерять добавление без каких-либо повреждений (см. код).
Я добавил «volatile», чтобы убедиться, что не происходит выравнивания пропусков: чтение только 32 бит переменной и других 32 бит на другую выборку, которая может быть разбита на 2 путем записи в середине из другого потока ,
Может ли мое предыдущее предположение (предыдущее утверждение) действительно произойти? Если нет, используется ли «изменчивое» использование (модификации свойств свойства могут произойти в любом потоке).
После прочтения 2 первых ответов. Я хотел бы настаивать на том, что способ написания кода неважно, если из-за параллелизма мы пропустим инкремент (хотим увеличивать с 2 потоков, но результат увеличивается только на один из-за параллелизма), если хотя бы переменная «_actualVersion» увеличивается.
Как ссылка, это часть кода, в котором я его использую. Он должен сообщать о сохранении действий (запись на диск) только тогда, когда приложение не используется.
public abstract class OptionsBase : NotifyPropertyChangedBase
{
private string _path;
volatile private int _savedVersion = 0;
volatile private int _actualVersion = 0;
// ******************************************************************
void OptionsBase_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
_actualVersion++;
Application.Current.Dispatcher.BeginInvoke(new Action(InternalSave), DispatcherPriority.ApplicationIdle);
}
// ******************************************************************
private void InternalSave()
{
if (_actualVersion != _savedVersion)
{
_savedVersion = _actualVersion;
Save();
}
}
// ******************************************************************
/// <summary>
/// Save Options
/// </summary>
private void Save()
{
using (XmlTextWriter writer = new XmlTextWriter(_path, null))
{
writer.Formatting = Formatting.Indented;
XmlSerializer x = new XmlSerializer(this.GetType());
x.Serialize(writer, this);
writer.Close();
}
}
Не то, что вы просили (поэтому добавили в качестве комментария), но я бы, вероятно, переместил вызов метода Save() на строку '_savedVersion = _actualVersion '. Таким образом, если Save() генерирует исключение, переменная _savedVersion не будет обновляться некорректно. – Baldrick
Почему вы сохраняете из потока 'Dispatcher' событие ?! –
@ Baldrick, я не могу делать то, что вы говорите (перемещение) из-за многопоточной импликации (я могу пропустить изменение версии, если я это сделаю). Но вы отчасти правы, где я должен предотвратить исключение моего кода. Благодаря ! –