|
Why do I hit "reply" before I think? Sorry!
I reread your question and realized that a) you're talking to the socket from all three threads (counting 3, the UI, as one), b) you're talking to the database from two of them (1 and 2, using your numbering). I have an app that does exactly that in production (it controls a bunch of stacker cranes and keeps track of what's stored where). It works well and looks like this:
1. The socket communication is handled by an object that queues inbound and outbound messages. It has a worker thread and uses locking to ensure that any access to its queues is thread-safe (I don't expose my private Queue<message> objects).
2. There is a supervisor object with a watchdog thread that monitors database updates (from other sources) and the inbound queue of the communications handler, and responds accordingly. It also has methods used by the UI to enqueue commands to the socket (the socket itself and the communications handler aren't exposed outside of the supervisor class). The watchdog thread and the UI use locks to ensure that they don't mess with any queues simultaneously.
3. The UI calls methods on the supervisor object when needed. Out of lazyness I don't use events as I don't want to mess with Invoke() in this case. Any status displays and so on can easily be handled by UI timers.
The point here is that only the supervisor object (and specifically, its watchdog thread) ever touches the database. It has its own connection which isn't exposed, so if I ever get the idea to let the UI touch the database, it has to use a separate connection (no threading or other issues).
Sorry for the previous somewhat redundant answers. I think I need some sleep now (2:27 AM here)...
--
Peter
|
|
|
|
|
Can you let me know any articles about DrawEllipse and FillEllipse methods, which can give clear about the concept.
|
|
|
|
|
What was wrong with the MSDN ones that you got with your google search ?
Christian Graus
Please read this if you don't understand the answer I've given you
"also I don't think "TranslateOneToTwoBillion OneHundredAndFortySevenMillion FourHundredAndEightyThreeThousand SixHundredAndFortySeven()" is a very good choice for a function name" - SpacixOne ( offering help to someone who really needed it ) ( spaces added for the benefit of people running at < 1280x1024 )
|
|
|
|
|
|
Hint: have a look at method names.
If the Lord God Almighty had consulted me before embarking upon the Creation, I would have recommended something simpler.
-- Alfonso the Wise, 13th Century King of Castile.
This is going on my arrogant assumptions. You may have a superb reason why I'm completely wrong.
-- Iain Clarke
|
|
|
|
|
I have a problem regarding the internal Protected.
I have a solution project that contains two projects.
1.Window application
2.class library.
namespace ClassLibrary1<br />
{<br />
public class Class1<br />
{<br />
internal protected int i = 0;<br />
}<br />
}
Now the following is the window application.I created a class file.There is am trying to access the proetected internal member of class library project.and it is accessibe there.
using ClassLibrary1;<br />
namespace WindowsApplication1<br />
{<br />
class Class2:Class1<br />
{<br />
public void bb()<br />
{<br />
<a href="http://zifiglio.blogspot.com/2007/03/c-accessibility-level-protected.html">http:
}<br />
}<br />
}
If you have an apple & I have an apple and we exchange our apples, then each of us will still have only one apple but if you have an idea & I have an idea and we exchange our ideas, then each of us will have two ideas!
|
|
|
|
|
You are deriving Class2 from Class1, that's why you are able to access the member.
protected internal does not mean protected and internal ; it means protected *or* internal .
To clear that up, a protected internal member will be visible to all other classes in the same assembly and derived classes everywhere - not just derived classes in the same assembly.
Cheers,
Vikram.
The hands that help are holier than the lips that pray.
|
|
|
|
|
Hello everyone,
Suppose Status is an int variable, which could be read and write by multiple threads.
When assign the value (write) of Status variable, I always use,
Interlocked.Exchange(ref Status, SomeValue);
My question is, in order to make write/read of this variable thread safe, could I access (read) the variable directly by accessing Status variable, for example
Console.write (Status);
if (Status > 0)
{
}
thanks in advance,
George
|
|
|
|
|
Reading and writing of an int are atomic operations, so the operations themselves are thread safe.
However, you may get unexpected results because the compiler can optimise the code because it relies on that a variable is only changed by the current thread, as you are supposed to use the volatile keyword if a variable needs special attention because it can be changed in multiple threads.
When you compile the code in your example, you might expect to get something like this (shown in pseudo code):
get Status into reg1
push reg1
call Console.Write(int)
get Status into reg1
compare reg1, 0
if lte jump .label
.label
Instead the compiler may optimise this code into:
get Status into reg1
push reg1
call Console.Write(int)
compare reg1, 0
if lte jump .label
.label
As you see, the code now doesn't get the value from the variable the second time, so it can enter the if statement even if the actual value of the variable has already changed.
Despite everything, the person most likely to be fooling you next is yourself.
|
|
|
|
|
Thanks Guffa,
1.
I doubt -- "Reading and writing of an int are atomic operations". Because if it is true, the system API Interlocked.Exchange overload for Int32 is useless. Any comments?
2.
It is great if you could provide some references to support the points -- "Reading and writing of an int are atomic operations". I am interested to learn new things.
regards,
George
|
|
|
|
|
George_George wrote: I doubt -- "Reading and writing of an int are atomic operations". Because if it is true, the system API Interlocked.Exchange overload for Int32 is useless. Any comments?
Either you don't know that the Interlocked.Exchange method does, or you misunderstood what I wrote. The documentation for the Interlocked.Exchange method says:
"Sets a 32-bit signed integer to a specified value and returns the original value, as an atomic operation."
So, it does two operations as an atomic operation. I wrote that reading and writing of an int are atomic operations, I didn't write that subsequent reading and writing of an int becomes a single atomic operation.
George_George wrote: It is great if you could provide some references to support the points -- "Reading and writing of an int are atomic operations".
"12.5 Atomicity of variable references
Reads and writes of the following data types shall be atomic: bool , char , byte , sbyte , short , ushort ,
uint , int , float , and reference types. In addition, reads and writes of enum types with an underlying type
in the previous list shall also be atomic. Reads and writes of other types, including long , ulong , double ,
and decimal , as well as user-defined types, need not be atomic. Aside from the library functions designed
for that purpose, there is no guarantee of atomic read-modify-write, such as in the case of increment or
decrement."
ECMA-334[^]
Despite everything, the person most likely to be fooling you next is yourself.
|
|
|
|
|
Thanks Guffa,
Your reply is great!
"reference types" -- means reference types of bool, char, byte, sbyte, short, ushort, uint, int, float (e.g. ref bool) or all reference types (including reference to a class)?
regards,
George
|
|
|
|
|
George_George wrote: "reference types" -- means reference types of bool, char, byte, sbyte, short, ushort, uint, int, float (e.g. ref bool)
No, you have to keep those two concepts separate. Sending a parameter by reference doesn't make it a reference type. A value type sent by reference is still a value type.
Despite everything, the person most likely to be fooling you next is yourself.
|
|
|
|
|
Thanks Guffa,
So in the great section "12.5 Atomicity of variable references" you quoted, "reference type" means references to classes' instances, right?
regards,
George
|
|
|
|
|
George_George wrote: So in the great section "12.5 Atomicity of variable references" you quoted, "reference type" means references to classes' instances, right?
No, "reference type" means class.
Despite everything, the person most likely to be fooling you next is yourself.
|
|
|
|
|
Thanks Guffa,
It is clear now.
regards,
George
|
|
|
|
|
Your question is not clear to me. Say status is a variable which will be modified by multiple threads, you can tell compiler not to optimize that filed by setting it as volatile . Else, you could acquire a lock before you read the variable value. Correct me if I got you wrong.
|
|
|
|
|
Thanks N a v a n e e t h,
1.
My question is, I want to make the access to variable Status thread safe. Some threads will write it and some threads will read it.
When write it, I will use Interlocked.Exchange method to set the value, and when read it, I will use Thread.VolatileRead method to read its current value. Is such solution thread safe?
2.
I think int assignment operation is not atomic and not thread safe, right?
regards,
George
|
|
|
|
|
George_George wrote: I will use Interlocked.Exchange method to set the value, and when read it, I will use Thread.VolatileRead method to read its current value. Is such solution thread safe?
It should be. Easy way is to mark the variable as volatile.
George_George wrote: I think int assignment operation is not atomic and not thread safe, right?
Assignment operation is not thread safe. You need some kind of locking here. volatile variables always have the latest data updated by each thread. So if you are looking for a flagging mechanism to end the running thread safely, volatile is the easy way to go.
|
|
|
|
|
Thanks N a v a n e e t h,
Only add volatile to read, no need to add to write?
regards,
George
|
|
|
|
|
George_George wrote: Only add volatile to read, no need to add to write?
You add volatile to the declaration of the variable. This will keep the compiler from optimising away reads and writes.
However, the only situation where a write would ever be possible to optimise away, would be if you assign it more than once in a code block without any alternative execution paths. Like this:
Status = 1;
Status = 0;
Despite everything, the person most likely to be fooling you next is yourself.
|
|
|
|
|
Thanks Guffa,
1.
Your sample about write assignment does not relates to volatile, right? I mean volatile will keep assignment of Status from optimization?
2.
So, volatile only works for read, not for write?
regards,
George
|
|
|
|
|
George_George wrote: Your sample about write assignment does not relates to volatile, right? I mean volatile will keep assignment of Status from optimization?
Right.
George_George wrote: So, volatile only works for read, not for write?
It works for both. Normally writes are just not optimised away at all (for member variables), so it's mostly the reads that are critical.
Despite everything, the person most likely to be fooling you next is yourself.
|
|
|
|
|
Thanks Guffa,
I am interested how volatile will impact write?
regards,
George
|
|
|
|
|
George_George wrote: I am interested how volatile will impact write?
The effect is that every write will be done.
For example, in this code:
for (int i = 0; i <= 1000; i++) x = i;
If the x variable is declared as volatile, the code is guaranteed to perform the loop and write every single value in the loop to the variable. If it's not volatile, the compiler could optimize away the entire loop, replacing it with simply:
x = 1000;
Despite everything, the person most likely to be fooling you next is yourself.
|
|
|
|
|