#C# FSW
1 messages · Page 1 of 1 (latest)
I am making a thread because this is likely to be a long convo
So anyways, the initial message was already too long.
I have to mention that in the code I attached, the fsw events are disabled in order for me to test the reload on a bind.
Now, I'll provide all the screenshots displaying proper execution, and execution triggered by the fsw.
Difference will be obvious, one gets executed mutliple times and keeps cutting off at the same part of the code, whilst the other one executes flawlessly each and every time.
- Proper execution
- FSW execution
It's likely a multithreading issue. Each callback you get is probably called on a new thread.
As for why it's called many times, you should check what arguments and parameters it's called with. Check the documentation for examples and API:
https://learn.microsoft.com/en-us/dotnet/api/system.io.filesystemwatcher?view=net-8.0
The one that is raised multiple times is on changed. This is mentioned in the documentation:
https://learn.microsoft.com/en-us/dotnet/api/system.io.filesystemwatcher.changed?view=net-8.0#system-io-filesystemwatcher-changed
yes, I went through that, but even when I implemented a time based check, it still cancelled the function exectuion(which is what i think is happening), when the other call was made, resulting in virtually nothing executing
I have an idea of what is happening(if my assumption is correct), I just don't know how to go about fixing it, and I can't say that it's well documented at all
Even if that's the case, I just can't understand how that cancels the other call mid execution, I don't know that's certainly happening, but it sure seems like it
an exception might be happening in a different thread, if that's the case you need to wrap your function in a try/catch and log the exception to Unity debug console
oh wow, that is such an excellent point, I didn't even think of that possibility o_0
since when does unity not log errors happening on a different thread?
never did as far as I know, you always need to capture the exception and log it manually
oh wow, I've been using it for 3 years, even wrote some multi threaded core, and never knew this, that's actually such a useful piece of knowledge
thanks for pointing it out, I'll see what I can come up with
who woulda thought, you nailed it!
had that issue so many times 😂
🤦♂️
well, at least I learned arguably one of the most useful things so far
just to make sure, the solution now is to execute all that stuff on the main thread, and implement deduplication logic too ofc, right?
I didn't follow too much the rest of the thread, but that sounds correct
you'll certainly need to jump back to the main thread to call those Unity functions
any suggestions for the api I should look into?
for moving back to the main thread you mean?
you can most likely find some implementations on Github or something like that, but it boils down to having some kind of Task queue being executed in the Update loop
in the simplest form, you can set a flag(bool) in the callback and check it in update(as well as reset).
More sophisticated solutions would use async await or event queue or something.
Hey, thanks a lot for your feedback, it truly means a lot!
I just tried this asset, but due to (mainly) it's Apache 2.0 license, I decided to not use it because my project uses GPL 3.0 and I wanna avoid any conflicts and complications.
It's also got a lot of bloat that I just cba to remove.
I decided to implement the simplest form of this, a bool check, I just don't know how safe it is?
Like, is it possible that the following code:
private bool _configChanged;
public void Update()
{
if (!_configChanged) return;
_configChanged = false;
HandleConfigChanged();
}
private FileSystemWatcher _configWatcher;
/// Sets up the FileSystemWatcher to monitor changes to the config file
private void WatchForConfigChanges()
{
_configWatcher = new()
{
Path = Path.GetDirectoryName(_configPath),
Filter = Path.GetFileName(_configPath),
NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.FileName | NotifyFilters.Size
};
_configWatcher.Changed += AcknowledgeConfigChanges;
_configWatcher.Renamed += AcknowledgeConfigChanges;
_configWatcher.Deleted += AcknowledgeConfigChanges;
_configWatcher.EnableRaisingEvents = true;
}
private void AcknowledgeConfigChanges(object sender, FileSystemEventArgs args) => _configChanged = true;
/// Handles config file being changed
private void HandleConfigChanged() { }
Could cause the Update to do the if check, see that the config has changed, then another change is acknowledged and _configChanged should be set to true but Update overwrites it with false due to a race condition?
sorry if this has a fairly obvious answer, I've done a fairly small amount of multi threading in the past so I don't have a lot of experience
sincerely I'm not sure, but if you want to be extra careful with that you can look into locks or similar strategies to keep things synchronized
Yea, it's a bit prone to race conditions. As you mentioned, it could potentially cause a consequent event to be skipped. You should use an atomic bool if you're worried.
Wait, there's no atomic in C#. It seems like interlocked is the C# alternative.
https://learn.microsoft.com/en-us/dotnet/api/system.threading.interlocked?view=net-8.0
Mutex is also a viable alternative:
https://learn.microsoft.com/en-us/dotnet/api/system.threading.mutex?view=net-8.0
You can also sugar it a bit with a lock:
https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/statements/lock