|
Apparently it all works out if i just ignore the error, and let the client time-out when it tries to send/receive data. It just doesn't seem right though...
My current favourite word is: I'm starting to run out of fav. words!
-SK Genius
Game Programming articles start - here[ ^]-
|
|
|
|
|
On the server side, I call BeginRead to wait for data - but I forgot to call EndRead . After adding that in i now get the expected IOException because the connection was closed, rather than the AcceptSocket method picking up... something.
My current favourite word is: I'm starting to run out of fav. words!
-SK Genius
Game Programming articles start - here[ ^]-
|
|
|
|
|
Is there any way to let my application know when the status of a Service has changed?
Or whenever theres a new entry in the Event Log?
Thx
|
|
|
|
|
|
|
I'm seeing a debug assertion failure in our code that makes me question how much I know about atomicity. Should this Debug.Assert ever fail?
private object syncObject = new object();
private bool isWorking;
void Foo()
{
lock (syncObject)
{
if (!isWorking)
{
isWorking = true;
new Action(DoSomething).BeginInvoke(OnDoSomethingCompletedAsync, null);
}
}
}
void DoSomething() { }
void OnDoSomethingCompletedAsync(IAsyncResult result)
{
lock (syncObject)
{
Debug.Assert(isWorking);
isWorking = false;
}
} Should this ever happen? I can say for certain that these are the only 2 functions I read or write to the isWorking field. Any idea what's going on?
Life, family, faith: Give me a visit.
From my latest post: "A lot of Christians struggle, perhaps at a subconscious level, about the phrase "God of Israel". After all, Israel's God is the God of Judaism, is He not? And the God of Christianity is not the God of Judaism, right?"
Judah Himango
|
|
|
|
|
Maybe you are calling Foo twice (Double click scenario) on the same object. Move OnDoSomethingCompletedAsync to an anon method and move isWorking inside of Foo and see what happens.
Need a C# Consultant? I'm available.
Happiness in intelligent people is the rarest thing I know. -- Ernest Hemingway
|
|
|
|
|
Foo gets called many times, over and over again. But that shouldn't matter, right?
Life, family, faith: Give me a visit.
From my latest post: "A lot of Christians struggle, perhaps at a subconscious level, about the phrase "God of Israel". After all, Israel's God is the God of Judaism, is He not? And the God of Christianity is not the God of Judaism, right?"
Judah Himango
|
|
|
|
|
It can and it does. That's just the way it goes, I suppose.
Need a C# Consultant? I'm available.
Happiness in intelligent people is the rarest thing I know. -- Ernest Hemingway
|
|
|
|
|
It can matter? Can you elaborate?
It doesn't seem like it should matter since it does nothing when isWorking == false
Life, family, faith: Give me a visit.
From my latest post: "A lot of Christians struggle, perhaps at a subconscious level, about the phrase "God of Israel". After all, Israel's God is the God of Judaism, is He not? And the God of Christianity is not the God of Judaism, right?"
Judah Himango
|
|
|
|
|
I can only imagine OnDoSomethingCompletedAsync being called twice in a row without a call to Foo() inbetween, so that isWorking is set to false when the second call to OnDoSomethingCompletedAsync is made.
I'm not sure if this can happen after two calls to Foo , and the (rare?) case that both async methods will be called after each other. I can't reproduce this behavior even in a while loop on my machine, though.
regards
modified 12-Sep-18 21:01pm.
|
|
|
|
|
OnDoSomethingCompletedAsync is called only through the code shown above. In short, it can be only be called when DoSomething is finished executing asynchronously. And DoSomething won't be started if it's already running. Bah.
Joe Woodbury writes below that I should have declared the fields volatile. I thought using a lock would be sufficient, but I will try the volatile declaration.
Life, family, faith: Give me a visit.
From my latest post: "A lot of Christians struggle, perhaps at a subconscious level, about the phrase "God of Israel". After all, Israel's God is the God of Judaism, is He not? And the God of Christianity is not the God of Judaism, right?"
Judah Himango
|
|
|
|
|
I also considered using volatile , but I found out something different - I inserted some WriteLine s to the methods, and this case happens quite a lot of times:
Enter Foo
Do something
Enter Result <---- huh? Shouldn't there be a lock?
Exit Result
Exit Foo
However, declaring the syncObject as static prohibits this case.
Maybe the lock isn't working properly?
regards
modified 12-Sep-18 21:01pm.
|
|
|
|
|
I can see a very narrow circumstance where it will fail. The problem is that isWorking is not declared volatile, so you aren't guaranteed it will actually be set before OnDoSomethingCompletedAsync() is invoked. If the optimizer caches the value and writes it after the scope of the lock, you could have a problem IF the thread switch happens just before that instruction.
Try private volatile bool isWorking;
Anyone who thinks he has a better idea of what's good for people than people do is a swine.
- P.J. O'Rourke
|
|
|
|
|
I considered that, but thought the lock keyword would take care of it. Volatile it is! Thanks.
Life, family, faith: Give me a visit.
From my latest post: "A lot of Christians struggle, perhaps at a subconscious level, about the phrase "God of Israel". After all, Israel's God is the God of Judaism, is He not? And the God of Christianity is not the God of Judaism, right?"
Judah Himango
|
|
|
|
|
From what I can see, as you are using BeginInvoke, the lock will not be active between after the invoke and just before the completion. Just a guess.
|
|
|
|
|
Right, the lock won't be active. However, we set the isWorking boolean while holding the lock. Thus, no other work would fire. (Theoretically.)
My only thought is that changes to the isWorking field aren't immediately seen by other threads due to CPU caching, even with the locks in there. I'm gonna try Joe Woodbury's suggestion of making the field volatile. Unfortunately, since this happens so rarely, I won't be able to see whether this fixed it for several months. Bah.
FWIW, I also pointed MS threading guru Joe Duffy over to this thread. I'm hoping he can enlighten me.
Life, family, faith: Give me a visit.
From my latest post: "A lot of Christians struggle, perhaps at a subconscious level, about the phrase "God of Israel". After all, Israel's God is the God of Judaism, is He not? And the God of Christianity is not the God of Judaism, right?"
Judah Himango
|
|
|
|
|
If thread1 calls Foo and then thread2 calls Foo while DoSomething is running, it will be allright because thread2 can't enter the lock owned by thread1. But if thread1 calls Foo again while DoSomething is still running on behalf of thread1's first Foo call, it can go wrong. Thread1 can enter Foo because it's the owner of the lock, so it starts a second DoSomething pool thread. Now when the first DoSomething pool thread is done (after the second DoSomething pool thread has started) it will set isWorking to false and release the lock in OnDoSomethingCompletedAsync. So when the second DoSomething pool thread is done and no one has meanwhile called Foo again, the second DoSomething pool thread will enter OnDoSomethingCompletedAsync and find isWorking = false.
|
|
|
|
|
Thanks for your detailed response, Frank.
Let me see if I'm understanding your correctly. You're saying that if Thread1 holds the lock inside Foo, spawns DoSomething on another thread, and then while still holding the lock, spawns DoSomething on another thread again, this can happen?
Life, family, faith: Give me a visit.
From my latest post: "A lot of Christians struggle, perhaps at a subconscious level, about the phrase "God of Israel". After all, Israel's God is the God of Judaism, is He not? And the God of Christianity is not the God of Judaism, right?"
Judah Himango
|
|
|
|
|
Sure, it can happen, because Thread1 is the owner of the lock and entering Foo again only increases the count on the lock, so that Thread1 has to leave it twice before another thread can enter.
|
|
|
|
|
Ok. Unfortunately, the thread doesn't enter the lock 2x.
Life, family, faith: Give me a visit.
From my latest post: "A lot of Christians struggle, perhaps at a subconscious level, about the phrase "God of Israel". After all, Israel's God is the God of Judaism, is He not? And the God of Christianity is not the God of Judaism, right?"
Judah Himango
|
|
|
|
|
OK, so that's not the reason. But isWorking can still be false in OnDoSomethingCompletedAsync:
1. Thread1 calls Foo and returns. Now isWorking=true, and PoolThread1 is processing DoSomething. No lock.
2. Thread2 calls Foo and returns. Still isWorking=true, and PoolThread2 is processing DoSomething. No lock.
3. PoolThread1 finishes, calls OnDoSomethingCompletedAsync and returns. Now isWorking=false. No lock.
4. PoolThread2 finishes, and because Foo has not been called again, it finds isWorking=false in OnDoSomethingCompletedAsync.
I don't know why you want isWorking to be true in OnDoSomethingCompletedAsync. If you really want to enforce it, you could enclose the whole DoSomething code inside a lock(syncObject) block. But that would be the end of parallel procession. So what is all this about? Or was it just an academic question?
|
|
|
|
|
Frank Horn wrote: 1. Thread1 calls Foo and returns. Now isWorking=true, and PoolThread1 is processing DoSomething. No lock.
2. Thread2 calls Foo and returns. Still isWorking=true, and PoolThread2 is processing DoSomething. No lock.
Nope. Thread2 calls Foo and returns, yes, but it does NOT spawn PoolThread2 because it sees isWorking = true.
Frank Horn wrote: I don't know why you want isWorking to be true in OnDoSomethingCompletedAsync
I want only 1 thread executing DoSomething at a time. The Debug assertion is a sanity check.
Life, family, faith: Give me a visit.
From my latest post: "A lot of Christians struggle, perhaps at a subconscious level, about the phrase "God of Israel". After all, Israel's God is the God of Judaism, is He not? And the God of Christianity is not the God of Judaism, right?"
Judah Himango
|
|
|
|
|
I want only 1 thread executing DoSomething at a time. The Debug assertion is a sanity check.
Then you could indeed run DoSomething within a lock(SyncObject) block. All threads wanting to call Foo would have to wait for the current DoSomething instance to finish.
Nope. Thread2 calls Foo and returns, yes, but it does NOT spawn PoolThread2 because it sees isWorking = true.
How does Thread2 see that isWorking = true? Does your class containing Foo a.s.o. have a public property IsWorking{get{lock(SyncObject){return isWorking;}}}, and is every call to xyz.Foo enclosed in an if(!xyz.IsWorking) block? Or in a while(true) block waiting for !xyz.IsWorking?
|
|
|
|
|
Frank Horn wrote: How does Thread2 see that isWorking = true?
Recall the Foo method code:
void Foo()
{
lock (syncObject)
{
if (!isWorking)
{
isWorking = true;
new Action(DoSomething).BeginInvoke(OnDoSomethingCompletedAsync, null);
}
}
} Foo will be called many times during app run, but should only spawn DoSomething if it's not currently working.
Life, family, faith: Give me a visit.
From my latest post: "A lot of Christians struggle, perhaps at a subconscious level, about the phrase "God of Israel". After all, Israel's God is the God of Judaism, is He not? And the God of Christianity is not the God of Judaism, right?"
Judah Himango
|
|
|
|
|