|
Hi all
I want to use volatile var in my multithreaded program.
Reading Writing operations are guaranteed to be thread safe.
What about comparing against other values?
Do you know if it is thread safe doing something like
<br />
static volatile long myValue = 10;<br />
if( myValue == 30 )
{<br />
} <br />
or if it is better to use Interlocked class approach?
Thanks in advance
CS
|
|
|
|
|
manustone wrote: if it is thread safe...
yes it is.
reading means: any way to obtain the value
writing means: any way to set a new (or same) value
therefore a conditional test is a read, and myValue++; is a read and a write.
manustone wrote: it is better to use Interlocked class approach?
depends on circumstances; with a simple value type, that can be entirely read in one CPU instruction, and when only one writer/producer is present, it is sufficient and Interlock is slower. In most if not all other cases, volatile is insufficient.
Luc Pattyn [Forum Guidelines] [My Articles]
I only read code that is properly indented, and rendered in a non-proportional font; hint: use PRE tags in forum messages
|
|
|
|
|
Hi Luc!
Thanks for your reply!
When you say "most if not all other cases volatile is insufficient" do you mean that when I use volatile keyword with NOT VALUE types i.e. REF TYPE thread safety is not guaranteed and that it is better to use other approach? (lock, interlock, etc.. ).
I starting digging about volatile stuff and it seems that a lot of people are really careful while using it.
|
|
|
|
|
Sharing a reference type amongst threads isn't straightforward; a simple volatile won't cut it. The object itself, or the code using it, must be organized to be "thread-safe" as an object typically has a state that encompasses all its data members.
And when in doubt, play it safe.
Luc Pattyn [Forum Guidelines] [My Articles]
I only read code that is properly indented, and rendered in a non-proportional font; hint: use PRE tags in forum messages
|
|
|
|
|
OK! It is clear!
Thank you very much and have a nice day!
CS
|
|
|
|
|
Luc Pattyn wrote: yes it is.
So... did you see he wrote volatile long ?
Reading a long is normally 2 reads (in 32bit mode) - volatile might have fixed that, but you can't apply volatile to longs
|
|
|
|
|
so it is extremely safe, it won't even compile.
you're right of course, I should have noticed long and volatile don't work together well when building for "anyCPU".
Luc Pattyn [Forum Guidelines] [My Articles]
I only read code that is properly indented, and rendered in a non-proportional font; hint: use PRE tags in forum messages
|
|
|
|
|
I didn't even notice. I read "integer" in the title of the post and after that my brain switched off and the reference to long never registered.
|
|
|
|
|
manustone wrote: Reading Writing operations are guaranteed to be thread safe.
I think the answer here is "Yes, but...". The following code example is not thread-safe and can produce two UniqueIdentifiers with the same value, despite the fact that _currentIndex is declared as volatile:
public class UniqueIdentifier {
private static volatile int _currentIndex = 0;
public int NewIndex {
get {
return _currentIndex++;
}
}
}
In this case, you would probably want to use Interlocked.
|
|
|
|
|
Hi DaviD, thank for your reply!~
Auch!!!
let me guess!
since _currentIndex++ are 1 read+ 1 write operations ( _currentIndex = _currentIndex +1 ) and since volatile guarantees thread safety on separate operation ( either read or write ), if another thread accesses between the read and the write the application will have a very bad issue.
Is correct what I am guessing?
|
|
|
|
|
yes, in general autoincrement is two distinct operations; even if the CPU may have an instruction to do all of it, if the language (and hence the compiler) does not tell you the autoincrement is guaranteed to be atomic, then you must play it safe and treat it as a read and a write, with a possible thread switch in between (and on multi-core another core intervening would also create havoc). There isn't a keyword that will save you, not volatile and certainly not register (which in C, not C#, suggests to the compiler to use a register rather than memory).
Luc Pattyn [Forum Guidelines] [My Articles]
I only read code that is properly indented, and rendered in a non-proportional font; hint: use PRE tags in forum messages
|
|
|
|
|
volatile long is not even legal and should not compile.
See MSDN: volatile (C#)[^]
So, you will have to use Interlocked .
|
|
|
|
|
Hi Harold!
Thanks for your email!
It is true and in the code I am writing I am actually using boolean.
It is consistent to what stated in MSDN so it doesn't compile.
Maybe it is a stupid question but do you know why?
|
|
|
|
|
Well, I wouldn't claim to know for sure, but I could hazard a guess..
At least on x86 in 32bit mode (but maybe 64bit mode as well, not sure?), as far as I know, the only way to do atomic stores/loads of 64bit is through lock cmpxchg8b (with zero in all* registers). It would have been possible for them to implement volatile longs that way, I guess they just didn't feel like it - maybe they felt it wouldn't be worth the effort?
* EDX:EAX and ECX:EBX, that's not really "all registers" but pretty close
|
|
|
|
|
<br />
using System;<br />
using System.Drawing;<br />
using System.Collections;<br />
using System.ComponentModel;<br />
using System.Windows.Forms;<br />
using System.Data;<br />
using System.IO;<br />
<br />
namespace FlashTest<br />
{<br />
public class Form1 : System.Windows.Forms.Form<br />
{<br />
private AxShockwaveFlashObjects.AxShockwaveFlash axShockwaveFlash1;<br />
private System.Windows.Forms.Button button1;<br />
private System.Windows.Forms.Button button2;<br />
private System.Windows.Forms.Button button3;<br />
private System.Windows.Forms.Button button4;<br />
private System.Windows.Forms.TrackBar trackBar1;<br />
private System.Windows.Forms.Label label1;<br />
private System.ComponentModel.Container components = null;<br />
<br />
public Form1()<br />
{<br />
InitializeComponent();<br />
<br />
}<br />
<br />
protected override void Dispose( bool disposing )<br />
{<br />
if( disposing )<br />
{<br />
if (components != null) <br />
{<br />
components.Dispose();<br />
}<br />
}<br />
base.Dispose( disposing );<br />
}<br />
<br />
#region Windows Form Designer generated code<br />
private void InitializeComponent()<br />
{<br />
System.Resources.ResourceManager resources = new System.Resources.ResourceManager(typeof(Form1));<br />
this.axShockwaveFlash1 = new AxShockwaveFlashObjects.AxShockwaveFlash();<br />
this.button1 = new System.Windows.Forms.Button();<br />
this.button2 = new System.Windows.Forms.Button();<br />
this.button3 = new System.Windows.Forms.Button();<br />
this.button4 = new System.Windows.Forms.Button();<br />
this.trackBar1 = new System.Windows.Forms.TrackBar();<br />
this.label1 = new System.Windows.Forms.Label();<br />
((System.ComponentModel.ISupportInitialize)(this.axShockwaveFlash1)).BeginInit();<br />
((System.ComponentModel.ISupportInitialize)(this.trackBar1)).BeginInit();<br />
this.SuspendLayout();<br />
this.axShockwaveFlash1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) <br />
| System.Windows.Forms.AnchorStyles.Left) <br />
| System.Windows.Forms.AnchorStyles.Right)));<br />
this.axShockwaveFlash1.Enabled = true;<br />
this.axShockwaveFlash1.Location = new System.Drawing.Point(32, 24);<br />
this.axShockwaveFlash1.Name = "axShockwaveFlash1";<br />
this.axShockwaveFlash1.OcxState = ((System.Windows.Forms.AxHost.State)(resources.GetObject("axShockwaveFlash1.OcxState")));<br />
this.axShockwaveFlash1.Size = new System.Drawing.Size(728, 504);<br />
this.axShockwaveFlash1.TabIndex = 0;<br />
this.axShockwaveFlash1.OnProgress += new AxShockwaveFlashObjects._IShockwaveFlashEvents_OnProgressEventHandler(this.axShockwaveFlash1_OnProgress);<br />
this.button1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));<br />
this.button1.Location = new System.Drawing.Point(32, 592);<br />
this.button1.Name = "button1";<br />
this.button1.Size = new System.Drawing.Size(80, 23);<br />
this.button1.TabIndex = 1;<br />
this.button1.Text = "Load";<br />
this.button1.Click += new System.EventHandler(this.button1_Click);<br />
this.button2.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));<br />
this.button2.Location = new System.Drawing.Point(128, 592);<br />
this.button2.Name = "button2";<br />
this.button2.Size = new System.Drawing.Size(80, 23);<br />
this.button2.TabIndex = 2;<br />
this.button2.Text = "Play";<br />
this.button2.Click += new System.EventHandler(this.button2_Click);<br />
this.button3.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));<br />
this.button3.Location = new System.Drawing.Point(224, 592);<br />
this.button3.Name = "button3";<br />
this.button3.Size = new System.Drawing.Size(80, 23);<br />
this.button3.TabIndex = 3;<br />
this.button3.Text = "Pause";<br />
this.button3.Click += new System.EventHandler(this.button3_Click);<br />
this.button4.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));<br />
this.button4.Location = new System.Drawing.Point(320, 592);<br />
this.button4.Name = "button4";<br />
this.button4.Size = new System.Drawing.Size(80, 23);<br />
this.button4.TabIndex = 4;<br />
this.button4.Text = "Stop";<br />
this.button4.Click += new System.EventHandler(this.button4_Click);<br />
this.trackBar1.Location = new System.Drawing.Point(24, 536);<br />
this.trackBar1.Maximum = 1;<br />
this.trackBar1.Minimum = -1;<br />
this.trackBar1.Name = "trackBar1";<br />
this.trackBar1.Size = new System.Drawing.Size(744, 45);<br />
this.trackBar1.TabIndex = 5;<br />
this.trackBar1.TickStyle = System.Windows.Forms.TickStyle.None;<br />
this.trackBar1.Value = -1;<br />
this.trackBar1.ValueChanged += new System.EventHandler(this.trackBar1_ValueChanged);<br />
this.label1.Location = new System.Drawing.Point(680, 600);<br />
this.label1.Name = "label1";<br />
this.label1.Size = new System.Drawing.Size(100, 16);<br />
this.label1.TabIndex = 6;<br />
this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);<br />
this.ClientSize = new System.Drawing.Size(792, 630);<br />
this.Controls.Add(this.label1);<br />
this.Controls.Add(this.trackBar1);<br />
this.Controls.Add(this.button4);<br />
this.Controls.Add(this.button3);<br />
this.Controls.Add(this.button2);<br />
this.Controls.Add(this.button1);<br />
this.Controls.Add(this.axShockwaveFlash1);<br />
this.Name = "Form1";<br />
this.Text = "Form1";<br />
((System.ComponentModel.ISupportInitialize)(this.axShockwaveFlash1)).EndInit();<br />
((System.ComponentModel.ISupportInitialize)(this.trackBar1)).EndInit();<br />
this.ResumeLayout(false);<br />
<br />
}<br />
#endregion<br />
<br />
[STAThread]<br />
static void Main() <br />
{<br />
Application.Run(new Form1());<br />
}<br />
<br />
private void button1_Click(object sender, System.EventArgs e)<br />
{<br />
axShockwaveFlash1.Movie = Directory.GetCurrentDirectory() + "\\A02_09.swf";<br />
axShockwaveFlash1.StopPlay();<br />
trackBar1.Maximum = axShockwaveFlash1.TotalFrames;<br />
label1.Text = axShockwaveFlash1.TotalFrames.ToString();<br />
}<br />
<br />
private void button2_Click(object sender, System.EventArgs e)<br />
{<br />
axShockwaveFlash1.Play();<br />
}<br />
<br />
private void button3_Click(object sender, System.EventArgs e)<br />
{<br />
axShockwaveFlash1.StopPlay();<br />
}<br />
<br />
private void button4_Click(object sender, System.EventArgs e)<br />
{<br />
axShockwaveFlash1.StopPlay();<br />
axShockwaveFlash1.FrameNum = -1;<br />
}<br />
<br />
private void axShockwaveFlash1_OnProgress(object sender, AxShockwaveFlashObjects._IShockwaveFlashEvents_OnProgressEvent e)<br />
{<br />
this.trackBar1.Value = axShockwaveFlash1.FrameNum;<br />
}<br />
<br />
private void trackBar1_ValueChanged(object sender, System.EventArgs e)<br />
{<br />
axShockwaveFlash1.FrameNum = trackBar1.Value;<br />
}<br />
}<br />
}<br />
<br />
Thanks All..
modified on Tuesday, November 24, 2009 1:22 AM
|
|
|
|
|
bekzod009 wrote: Thanks
And what is your problem?
|
|
|
|
|
I inherited a project at my job, and there is a line of code that is giving me an error. I am having trouble figuring it out.
In the method below, data is being pulled from a table, and put into a CustomerData object. The "Expiration" line, which is a DateTime, is the one that is erroring. If I take out this part: "() => new License()" in the .FirstOrDefault method, it compiles, but when I click on the part that populates the grid I get "Object reference not set to an instance of an object.". If I try to compile with this part: "() =&gt; new License()" it gives me this error: "The type arguments for method 'System.Linq.Enumerable.FirstOrDefault<TSource>(System.Collections.Generic.IEnumerable<TSource>, System.Func<TSource,bool>)' cannot be inferred from the usage. Try specifying the type arguments explicitly."
If I assign "Expiration" to a static DateTime, then it works fine and populates the return with all the same date/time.
So, I think the linq part of the statement is wrong and I am getting null back (when the field is not nullable), or I need to specify the type somewhere in there.
Any help would be appreciated!
internal static IEnumerable<CustomerData> GetCustomers(this HttpRequest request)
{
var dc = new RootDataContext();
return dc.Customers.ToList().Select(c => new CustomerData()
{
CustomerId = c.CustomerID,
StoreNumber = c.StoreNumber,
StoreName = c.StoreName,
OwnerName = c.OwnerName,
City = c.City,
State = c.State,
TimeZone = c.TimeZone,
//Compile time error, "specify type"
//Expiration = c.Licenses.Where(l => l.ProductID > 1002).OrderBy(l => l.Expiration).FirstOrDefault(() => new License()).Expiration,
//Compiles, errors "null reference"
//Expiration = c.Licenses.Where(l => l.ProductID > 1002).OrderBy(l => l.Expiration).FirstOrDefault().Expiration,
//works, all the same datetime
//Expiration = new DateTime(2010, 12, 10),
Trial = c.Licenses.Where(l => l.ProductID > 1002).Any(l => l.Trial),
InventoryDate = c.Products_Database_Eagle != null ? c.Products_Database_Eagle.InventoryDate : default(DateTime),
Upload = c.Products_Database_Eagle != null ? c.Products_Database_Eagle.Upload : false,
Finalize = c.Products_Database_Eagle != null ? c.Products_Database_Eagle.Finalize : false,
Registration = c.RegistrationKey,
});
}
|
|
|
|
|
Looks like the search failure is returning a null license (since you specified FirstOrDefault ) whose DateTime member you're trying to access.
/ravi
|
|
|
|
|
So what would I do there?
I cant leave it blank, or else it gives me a object reference exception.
The code that was in there "() => new License()" has a compile time error that says "The type arguments for method 'System.Linq.Enumerable.FirstOrDefault<TSource>(System.Collections.Generic.IEnumerable<TSource>, System.Func<TSource,bool>)' cannot be inferred from the usage. Try specifying the type arguments explicitly."
I guess I need to know how to specify the type explicitly. I think it is trying to create a new License if it cannot find one in the select statement, which is why it leaves it blank if it cannot find one.
|
|
|
|
|
Calvin Bell wrote: So what would I do there?
You need to evaluate your design and decide how the code should work, rather than simply tweaking the code to compile and run under circumstances. What DateTime do you want to do if the license is not found? A null reference, DateTime.MinValue , something else? The choice is yours.
/ravi
|
|
|
|
|
my server implements a reading thread that blocks until data is received.
what I'd like to do is have a designated thread that only writes as data becomes available (an event would be created that contains the TcpClient in the event argument).
Therefore the question: is it possible to use TcpClient.GetStream() twice for the same TcpClient ?
|
|
|
|
|
It's not possible.
'tcpclient.getstream() ' can get all btye[] by server socket sending.
April
Comm100 - Leading Live Chat Software Provider
modified 27-May-14 21:53pm.
|
|
|
|
|
Yes, it's possible.
You can't read or write by two threads, but having a thread that only reads and a thread that only writes is perfectly possible. I always do this but, in fact, I call GetStream only once, and pass the returned stream as the parameter to the threads, but I really think this don't change anything.
Also, be carefull not to close the stream before you finished, as closing the stream will also close the tcp/ip connection.
|
|
|
|
|
passing the TcpClient object around and calling GetStream() once in the read thread and once in the write thread worked just fine.
Since I found this out I have updated my code to use a secure socket and now I'm passing around a NegotiateStream object (but no need to call GetStream)
|
|
|
|
|
Hi,
In c# i generated HTML report (colored).
I am using Webbrowser control.
I need to print it. But unfortunately i cannot print the color (background color). why?
A sample report is as below.
<html>
<head>
<title>Test</title>
</head>
<body align=center >
<table align=center border=0 width=1000>
<tr>
<td align=center class=title style='border:2px solid red;'>110P-1 PRODUCTION SCHEDULE</td>
</tr>
</table>
<table align=center border=1 width=1000 cellspacing=0 cellpadding=0>
<tr>
<td colspan=3 align=right> <b>TOTALS:</b> </td>
<td align=center ><b>22160.00</b></td>
<td align=center ><b>15828.57</b></td>
<td align=center ><b>18000.09</b></td>
<td align=center><b>2971.36</b></td>
<td align=center><b>33</b></td>
<td > </td>
</tr>
<tr>
<td align=center ><b>DEL.DATE</b></td>
<td align=center ><b>COLOUR</b></td>
<td align=center><b>ADDRESS</b></td>
<td align=center ><b>L/M</b></td>
<td align=center ><b>HOURS@1.4m</b></td>
<td align=center ><b>COMPLETE</b></td>
<td align=center ><b>REMAIN HOURS</b></td>
<td align=center ><b>PACKS</b></td>
<td align=center ><b>STATUS</b></td>
</td>
<tr><td align=center > 20/11/2009</td>
<td align=center style='background-color:#FF8C00;'> </td>
<td align=center > Hamilton Iland</td>
<td align=center > 20310.00</td>
<td align=center > 14507.14</td>
<td align=center> 18000.09</td>
<td align=center > 1649.94</td>
<td align=center > 33</td>
<td align=center > </td></tr>
<tr><td align=center > 16/11/2009</td>
<td align=center style='background-color:#14A0E6;'> </td>
<td align=center > Bankstown</td>
<td align=center > 1250.00</td>
<td align=center > 892.86</td>
<td align=center > 0.00</td>
<td align=center > 892.86</td>
<td align=center > </td>
<td align=center > </td></tr>
</tr>
</table>
</body>
---------------------------------- ---------------------
I am using .NET framework 3.5
I have color printer. and if i changed table border to red, blue, etc for border, it prints in color.
It only does not work with table cell (TD) background color.
Thanks in advance
Shukra
|
|
|
|
|