|
Hi!
But in order for the second thread to stay blocked i need to put the code in the first thread protected by a syncLock block right?
Never say never
|
|
|
|
|
All of your access to the array much use SyncLock, not just the main thread enumeration. If every access to the array goes through SyncLock, there's no threading issues. So, read up on Array.SyncLock[^]. Put some test code together and play with it!
RageInTheMachine9532
"...a pungent, ghastly, stinky piece of cheese!" -- The Roaming Gnome
|
|
|
|
|
You need to do two things:
1) Ensure that no other thread is actively modifying the collection or any of it's members.
2) Ensure that no other thread is currently reading any collection members since collection access is not inherently threadsafe.
MSDN does a generally poor job of describing thread synchronization in VB.NET. Their examples explain just enough to get you into trouble, mostly.
The problem is a synckLock, aka critical section, will only protect a section of code. If you put a critical section on, for example, the collection Delete method this will ensure that only one thread can delete a collection member at any given time, but it provides no guarantees that other threads are not currently enumerating the collection, so you would still get errors.
The only way you could accomplish thread safe access using a syncLock (aka critical section) with a collection is if you put the syncLock on the enumeration code, AND you ONLY modify a collection or it's members within the For ..Next loop.
This has two very obnoxious side effects:
Of course, only allowing write access within a For .. Each enumeration results in awkward and inefficient code.
All other threads are blocked when a single thread accesses the collection for any reason. What you really want is to only lock the collection when one thread needs to modify it.
So syncLock really is not suitable for this scenario. The correct way to do this is to implement locking if and only if a thread needs to modify the collection.
I'll explain how to do this the old-fashioned way with mutexes and semaphores.
The following procedure will ensure thread safe collection usage with minimal unneccessary locking.
Execute the following steps to "write" protect a collection, i.e. when a thread intends to access the collection for modification.
1) When a thread wishes to modify the collection or it's members it must first acquire a mutex. The mutex is only available to one thread at any given time and is used to block all other threads from either read or write access to the collection.
2) After the "writer" thread acquires the mutex, it must wait until all other threads have released their semaphores which occurs when all other threads which are actively accessing the collection as "readers" have finished.
3) When all semaphores are signalled, the "writer" is ensured it is sole access to the collection and the collection or any of it's members may safely be modified because all other threads are now blocked from read or write access.
4) When the writer is done modifying the collection or any of it's members, it releases the mutex, which unblocks all other threads.
Execute the following steps before any thread accesses the collection for read purposes only.
1) When a thread wishes to read the collection by either item access or enumeration it must first acquire a mutex. If the thread cannot acquire the mutex, it means another thread is possibly writing to the collection, so it must wait.
2) After the "reader" thread acquires the mutex, it should acquire a semaphore to signal to any subsequent writers that a thread is accessing the collection for reads.
3) Release the mutex so the next reader may acquire it long enough to get the next semaphore.
4) When the reader is done accessing the collection or any of it's members, it releases the semaphore.
You should implement all the above actions in a class that wraps your collection and provides thread-safe access to it.
VB.NET provides a ReaderWriterLock class that essentially implements the same operations I describe above behind the scenes. But I suggest you use the Win32 APIs to create your own mutex/semaphore code for synchronization so you can learn how it really works. VB.NET wrappers are fine if you understand threading synchronization fundamentals already. If you don't, you are a lot better off working directly with Win32 primitives.
Robert
|
|
|
|
|
Hi! Thx for the answers.I've used before semaphores and mutexes with C in linux.I wanted a quick way to make sure the concurrency doesn´t raise any problems.
My really problem isn´t how the locking mechanism works, but a "second level" of locking.For example o use sockets read async.When i complete a read i have directly the object which i keep in the collection(along with many others).The thing is that at this point i need to lock just the object, not the entire collection.But when i'm enumerating the collection i lock it because i want to access all objects.So, i'm divided in how i should do that, because if i lock the collection but that in the read function have access to the object i'll be able to modify it!!!That's not right.
Sugestions?
Never say never
|
|
|
|
|
Mutexes and Semaphores will still work. Keep in mind that mutexes and semaphores do not "lock" anything. They are just a means of inter-thread communications.
A mutex says "I am in the process of modifying some object. No other threads should attempt to access this object until I am done". A semaphore says "I am in the process of accessing some object. No other threads should attempt to modify this object until I am done."
The developer still has to write all the code that ensures each thread obeys the rules when accessing an object.
carlos_rocha wrote:
When i complete a read i have directly the object which i keep in the collection(along with many others).The thing is that at this point i need to lock just the object, not the entire collection.But when i'm enumerating the collection i lock it because i want to access all objects.So, i'm divided in how i should do that, because if i lock the collection but that in the read function have access to the object i'll be able to modify it!!!That's not right.
You have to set a reference to the object somewhere. It does not matter if you are enumerating the collection or setting a reference directly to an object that exists in the collection. Before you access a member of the collection by any method of access - direct or by enumeration (both of which require you to set a reference to the object) the thread should acquire a semaphore to notify all other threads that it is accessing an object and they cannot modify any objects or the collection itrself. Before you attempt to modify either an object or the collection itself, a thread must acquire the mutex and wait for all semphores to become signalled. This means that no other thread is actively accessing any object in the collection.
In this scenario, you are not sychronizing the objects themselves, you are synchronizing read and write operations on both the collection itself and all of it's members. This will work as long as you are not frequently modifying data either at the collection level or at the member object level.
If you are frequently modifying member objects then you may find that synchronizing on read and write operations causes excessive wait times. In this case you have to implmement synchronization at two levels - collection add/deletes as a top level and per-object synchronization at the member level. This is a lot more complicated.
Before I would implement this degree of synchronization I would carefully examine my application design. Multiple threads frequently accessing common data for anything other than read only (inherently threadsafe) operations is not a scenario that is generally efficient. Threads are mostly useful only when there are minimal concurrency issues. If your application requires more than minimal synchronization, multi-threading will tend to make it slower than just using a single thread.
Or you need to review your overall design.
For example, suppose your application needs to read a lot of data, populate objects from the raw data, and put them in a collection (or it needs to continuously read data in real-time). The application then modfifies some of the objects. The logical way to multithread this would be to have a background thread read data asynchronously, and populate objects and save them in a local collection. Periodically the background thread should stop reading data, and notify the main thread that it has a new set of objects ready. The main thread then adds the new objects to a collection that it owns exclusively, tells the background thread it has taken ownership of the data, and then the background thread drops all references to the existing objects and goes and gets new data.
Threading is generally only useful in the following scenarios:
Background processing of data passed off from a main thread to a worker thread, for example slow dataset processing/updates using data already modified by the main thread, or preparing a print job.
Background processing of data read from an external source to prepare it to be used by the main application, for example slow queries, downloading data from a webserver, or real time data acquisition systems.
Thread pooling applications that require a thread to be assigned to a given operation to ensure all operations remain responsive. For example an IVR system may assign threads on a per channel basis so that each caller gets a response in a timely manner.
In the first two cases, thread synchronization occurs infrequently - only when threads need to transfer data from one thread to another. In the third case there is no concurrency, each thread acts independently.
Although there are always exceptions, in general if significant thread concurrency issues exist, it probably indicates someone is trying to use threads based on the totally misguided notion that multiple threads will somehow "speed up" an application.
carlos_rocha wrote:
I wanted a quick way to make sure the concurrency doesn´t raise any problems.
Sorry, there is no quick way to ensure concurrency issues don't arise. SynchLocks (critical sections) are deceptively easy to code but are by far the most difficult form of synchronization to use correctly. The only place you'll find "quick ways" are in the MSDN examples which are practically useless in real applications. The MSDN examples do not even bother to show the absolute minimum implementation required to use a SynchLock. Any code that enters a critical section absolutely must have a Finally block to ensure that no matter what happens in the protected code the thread always exits the critical section and releases the lock. The MSDN glosses over even this basic fundamental, much less describing any of the numerous subtleties of using SynchLocks.
Robert
|
|
|
|
|
Hi!Thanks on the great insight.I think the app is fairly well designed.My issue is that i have a thread that does some processing with one object and another thread (that enumerates the collection) is checking out the state of the objects.When the processing level determines that the object has reached the end of its life it changes its state and the cleanup thread (the one that enumerates the collection) deals with the object cleanup and removal.I'm trying to synchronize at these two levels.
What about readerWriterLock? That was my second choice.Doesn´t this strategy ensures security for reads and writes like you said? If this isn't ok i'll use mutexes and semaphores.
Note:i didn´t had so far any concurency issue but i'm sure that when i release the app for beta testing some will go wrong
Once again thanks for all the help.
Never say never
|
|
|
|
|
ReaderWriterLock is a VB.NET class wrapper for mutexes and semaphores. The advantage is it makes code quicker to write. The disadavantage is that it obscures what is really happening. The fundamental synchronization technique is the same as using mutexes and semaphores directly.
Robert
|
|
|
|
|
We’ve deployed an app on 20 machines using xcopy deployment. The exe is on the intranet and everyone has a shortcut to it. Yesterday we corrected a bug we found in the initial rollout and I came in this morning early to replace the exe with the updated exe and received the error “Cannot copy… It is being used by another person or program” which means that one of our 20 employees simply locked their computer with the application still running.
Is there a utility that I can use to see which employee is accessing this exe file?
Lost in the vast sea of .NET
<a href="http://www.komputing.com/Pricelist.html">Visit my website at www.komputing.com</a>
|
|
|
|
|
Now you know why it's bad idea to do that! Install it on the workstations to avoid this in the future. Why? Try to find out who has the file opened when you have 500+ workstations using it. You won't come up with 1 or 2 users who have left for the night, but you will come up with a couple dozen...
RageInTheMachine9532
"...a pungent, ghastly, stinky piece of cheese!" -- The Roaming Gnome
|
|
|
|
|
I agree and disagree....
I agree that it might not be a good idea for 500 people to share the same exe, but on the other hand if we load the exe locally on 500 systems we also have the issue of visiting 500 systems each time we want to upgrade.
So far we're a small shop with small apps, but I agree, as we grow and have vb apps on many computers we'll have to re-evaluate our implementation.
We're waiting for the final version of VS 2005 to come out this summer / fall to test and start using the ClickOnce technology, but till then our xcopy deployment works.
I also have a coworker looking for the same type of concept, but they're looking for code, that will show if a file is being accessed and if so, by who. Basically the code would continue a copy if the file was not accessed or alert the client that the file is being accessed and the file copy failed.
Any suggestions?
Lost in the vast sea of .NET
<a href="http://www.komputing.com/Pricelist.html">Visit my website at www.komputing.com</a>
|
|
|
|
|
No you don't. There's a bunch of different software manangement solution out there. SMS Server, Altiris, Tivoli, ... They take care of deploying the software for you, so you don't have to visit those machines...
RageInTheMachine9532
"...a pungent, ghastly, stinky piece of cheese!" -- The Roaming Gnome
|
|
|
|
|
I haven't found any kind of a "WhoHas" utility for Windows. Netware, yes, all over the place, but not Windows. It makes me wonder if it's even possible to find out who has the file open...
RageInTheMachine9532
"...a pungent, ghastly, stinky piece of cheese!" -- The Roaming Gnome
|
|
|
|
|
Use Task Manager on the server to kill the running executable. Then you can copy the file.
Robert
|
|
|
|
|
hi,
i am developing a web service in vb.net. in this, what is required is.. that one web service calls the other. this is possible. however it is also required that the web service displays a message and takes user input. how do we take input from a user in a web service..?
pl reply
|
|
|
|
|
You don't! Web Services don't expose a user interface at all.
You're application that calls the Web Service must put up the user interface and call the Web Service with the required data.
RageInTheMachine9532
"...a pungent, ghastly, stinky piece of cheese!" -- The Roaming Gnome
|
|
|
|
|
I want to prevet users from errors
Should I use "On Error goto" statement or "Try catch end try" block.
Although i dont want my program to rum slower due to error handling.
Do you know which method is faster?
Thanks in advance
|
|
|
|
|
|
Try/Catch blocks are very much the better way to go. Error handling doesn't add a huge overhead to your code, so I don't know why that's a concern... If your code errors out, Error Handling definately wins the speed competition, because if you don't the error, your code comes to a screeching halt.
RageInTheMachine9532
"...a pungent, ghastly, stinky piece of cheese!" -- The Roaming Gnome
|
|
|
|
|
sure, but you cannot apply any Resume ... (even if - i aggree - goto s are quite bad to use...
TOXCCT >>> GEII power [toxcct][VisualCalc]
|
|
|
|
|
If your code is written correctly, why on earth would you need to?
RageInTheMachine9532
"...a pungent, ghastly, stinky piece of cheese!" -- The Roaming Gnome
|
|
|
|
|
while programming in console mode, this becomes very useful when getting a bad user input and want to get it again until the user type its value correctly...
this can't be done with exceptions (try and catch blocks) except if you use explicit goto s, that behavies the same...
TOXCCT >>> GEII power [toxcct][VisualCalc]
|
|
|
|
|
Wanna bet?! Just a little something off the top of my head...
Dim validInput As Boolean = False
Dim choice As Integer
Do
Try
choice = Console.ReadLine()
...Whatever else you need...
If choice is valid Then
validInput = True
End If
Catch ex As Exception
...Whatever you want here...
End Try
Loop While Not validInput
RageInTheMachine9532
"...a pungent, ghastly, stinky piece of cheese!" -- The Roaming Gnome
|
|
|
|
|
Ok everybody,
This may sound kinda silly but this is what i m unable to do.
I was working on VS.NET and had MSDN fine and working. Now i need to work on VS6 but i unable to use MSDN through VS6 although its installed on my machine. How do i link MSDN with VS6???
Laddoo
|
|
|
|
|
I think you got a good question. Anybody out there to solve this?
Smith
KB Team
|
|
|
|
|
You installed both on the same machine? The MSDN Library hasn't supported integration with Visual Studio 6 for roughlt the last 2 years...
I can't remember if you can install two different editions of MSDN side-by-side. IMHO, I don't think you can...
RageInTheMachine9532
"...a pungent, ghastly, stinky piece of cheese!" -- The Roaming Gnome
|
|
|
|