It is currently November 29th, 2020, 8:03 pm

[help] C# and multithreading

Share and get help with Plugins and Addons
User avatar
jsmorley
Developer
Posts: 21552
Joined: April 19th, 2009, 11:02 pm
Location: Fort Hunt, Virginia, USA

Re: [help] C# and multithreading

Post by jsmorley »

FlyingHyrax wrote: You can keep multiple threads from mutating ConnectionType and ReturnValue with the Monitor/Lock construct. That should be relatively straightforward.
In this particular plugin (and really in any plugin in Rainmeter) there will never be multiple threads. However, I do need to protect the read of things like "ConnectionType" and "FinishAction" and to some extent "ReturnValue" from changes that happen due to the measure being "dynamic" and having one of the measure options changed in Reload(). Normally Reload() is only read once when the skin with the measure is loaded, but with DynamicVariables, it is read on every measure update.
User avatar
Aragas
Posts: 64
Joined: December 24th, 2012, 6:56 pm
Location: Russia, Moscow

Re: [help] C# and multithreading

Post by Aragas »

Yes, with no static we probably could fix that. One of the problem is i can't call normally Dispose() from static Plugin. Nope. Don't know how to make it.
Last edited by Aragas on December 21st, 2013, 4:52 pm, edited 1 time in total.
User avatar
jsmorley
Developer
Posts: 21552
Joined: April 19th, 2009, 11:02 pm
Location: Fort Hunt, Virginia, USA

Re: [help] C# and multithreading

Post by jsmorley »

Aragas wrote:About separating. Store all option in one value can cause potentially errors. Rainmeter calls Reload() and Update() separate, so ConnectionType and ReturnValue is't synchronised.
A sample:
We need to get Internet status. Rainmeter calls Reload(), where we get ConnectionType. Then he calls Update(). Plugin read ConnectionType and starts the Thread. And, because we can't wait the Thread ends and give us the value, he will give back Rainmeter 0.0 or something like that. We will probably get the value when Rainmeter secondly calls Update(). 20 second haven't passed, so we will not make a new Thread. We just give Rainmeter the value. But! We could make before the second Update() a new Reload() call, where we want get the Network status. We make a new Thread. The second Update() can give us the Network status, not the Internet.
By separating the values we can pass that error. but this only works if i have right understand that Rainmeter can call whenever Reload().
That may be, but separating them into two different return value variables based on ConnectionType isn't the answer in my opinion. In this simple plugin, it would be ok, but not in a more complex plugin with tons of options, and parent / child relationships and all that.
I really think there must be a more graceful way than brute force.

I suspect some kind of Mutex is going to be the answer, but not sure yet.
User avatar
Aragas
Posts: 64
Joined: December 24th, 2012, 6:56 pm
Location: Russia, Moscow

Re: [help] C# and multithreading

Post by Aragas »

jsmorley wrote: That may be, but separating them into two different return value variables based on ConnectionType isn't the answer in my opinion. In this simple plugin, it would be ok, but not in a more complex plugin with tons of options, and parent / child relationships and all that.
I really think there must be a more graceful way than brute force.

I suspect some kind of Mutex is going to be the answer, but not sure yet.
Hm. We have a big Measure with parents\children. If we will have just ReturnValue it would be really hard to debug it.
I think so. We need to make it working right by any way we find. If it will work, then we can see what we can improve. What about that?
User avatar
Aragas
Posts: 64
Joined: December 24th, 2012, 6:56 pm
Location: Russia, Moscow

Re: [help] C# and multithreading

Post by Aragas »

We have yet 3 static things - Dispose(), _networkThread and _canceler. If we find how to call Dispose() from Plugin, i'll fix it. I have a solution, but then i'll rewrite Plugin class, what is unacceptable
User avatar
jsmorley
Developer
Posts: 21552
Joined: April 19th, 2009, 11:02 pm
Location: Fort Hunt, Virginia, USA

Re: [help] C# and multithreading

Post by jsmorley »

What I really want (aside from this plugin at all really) is to find a generic approach that works for threading in C# plugins in Rainmeter. I want it do to exactly what it "must" do to function properly, and no more.

To be honest, I gave up on really trying to understand what your code was doing, as I just had too much trouble with all the different conventions for naming variables and functions, and the ten different ways the term "cancel" was used without any naming that made it at all clear what they were meant for.
User avatar
Aragas
Posts: 64
Joined: December 24th, 2012, 6:56 pm
Location: Russia, Moscow

Re: [help] C# and multithreading

Post by Aragas »

jsmorley wrote: 1) Protect against race conditions if the measure is set to DynamicVariables=1 (which will cause Reload() to execute on every measure update, potentially causing a change in variables like ConnectionType while Update() is still running.
Then we need to move calling threads to Reload(). I think there should be first calling. And then make new calls from update, when Count=0.
FlyingHyrax
Posts: 251
Joined: July 1st, 2011, 1:32 am
Location: US

Re: [help] C# and multithreading

Post by FlyingHyrax »

In this particular plugin (and really in any plugin in Rainmeter) there will never be multiple threads.
..but aren't there? There is the thread that the plugin started in originally, and the thread that you are running CheckConnection in. CheckConnection needs to know that the value of ConnectionType isn't mutating out from underneath it.

I think a Monitor would work just fine: if you lock the ConnectionType while setting it in Reload(), and also lock it in your new thread, then the two should not be able to access it simultaneously - if ConnectionType is running in the second thread it will have the lock and Reload will have to wait for it to release before modifying ConnectionType.

I think a Mutex in C# allows for cross process shared memory. That would be overkill in this case. (Though we may just be having a semantic issue where your Mutex is my Monitor?)
msdn wrote:The most common kind of lock goes by many different names. It is sometimes called a monitor, a critical section, a mutex, or a binary semaphore...
http://msdn.microsoft.com/en-us/library/system.threading.mutex%28v=vs.80%29.aspx
http://msdn.microsoft.com/en-us/library/system.threading.monitor%28v=vs.80%29.aspx
Last edited by FlyingHyrax on December 21st, 2013, 5:18 pm, edited 2 times in total.
Flying Hyrax on DeviantArt
User avatar
jsmorley
Developer
Posts: 21552
Joined: April 19th, 2009, 11:02 pm
Location: Fort Hunt, Virginia, USA

Re: [help] C# and multithreading

Post by jsmorley »

Aragas wrote: Then we need to move calling threads to Reload(). I think there should be first calling. And then make new calls from update, when Count=0.
That might not be a bad idea.
FlyingHyrax
Posts: 251
Joined: July 1st, 2011, 1:32 am
Location: US

Re: [help] C# and multithreading

Post by FlyingHyrax »

jsmorley wrote: That might not be a bad idea.
...I will observe with great interest.

Also - and this is totally unrelated - I'm not sure if it's GitHub or Visual Studio, but something somewhere does a really bad job preserving appropriate indentation.
Flying Hyrax on DeviantArt