using System;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormsApp1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
Task.Run(() => { SomeWork(); });
}
private void SomeWork()
{
while (true) {
// Check config
if (Config.SomeBool) {
// Do something
} else {
// Do something else
}
Thread.Sleep(100);
}
}
private void checkBox1_CheckedChanged(object sender, EventArgs e)
{
Config.SomeBool = checkBox1.Checked;
}
}
public static class Config
{
public static bool SomeBool { get; set; }
}
}
Let's say in my winforms application, I have a thread running in the background doing some work in a loop. It needs to to different things based on some Config
that can be modified by user on the UI thread.
C# Specification says
Reads and writes of the following data types shall be atomic: bool, char, byte, sbyte, short, ushort, uint, int, float, and reference types.
I don't quiet understand how "atomic" works in C#. Let's get back to my program above, if I manually changes some value of Config
class via the checkbox, is the background thread always gonna receive the latest Config.SomeBool
value, or should I lock it like this:
private readonly static object _someBoolLock = new object();
private static bool _someBool;
public static bool SomeBool
{
get
{
lock (_someBoolLock) {
return _someBool;
}
}
set
{
lock (_someBoolLock) {
_someBool = value;
}
}
}
I'm asking because the program kinda runs "fine" without the lock but I can't say I tested it enough to be sure that it's okay to do so. The static Config
class has many more properties in my real program, I wonder if I should lock them all, given they may be read by othe threads?
EDIT: I forgot to mention that I don't care if Config.SomeBool
become false
while // Do something
, all I care is everytime the background thread checks the value, it will always be the same as shown on the UI. If user changes it during // Do something
, the background thread should finish it nontheless.
While trying to search for this problem I got many conflicted answers most likely from unexperienced coders like myself. Basically it comes down to:
- Will the value
Config.SomeBool
be cached somewhere in the background thread? If so, how long would it be held in cache? (If this loop gets the old value, would next loop get the new value or still the old one?) - What's the correct approach to ensure the value to be "latest" every time it's read by any thread?
EDIT: I've post what I read during the past few days as an answer below. If you found this post from a search result, please do read it. The short answer to the question in the title is "no".