![]() | |
![]() |
| | Thread Tools | Search this Thread | Display Modes |
#1
| |||
| |||
|
#2
| |||
| |||
|
#3
| |||
| |||
|
|
Randy, I'm not sure if you've considered any of the following: Are you using any multi-threading in your app? If so are you using Invoke/InvokeRequired correctly? I've found that those "hard-to-reproduce" bugs are often the result of incorrect threads accessing a control. There may also be a race condition happening - InvalidOperationException is raised when a object is in the wrong state such as calling Current before MoveNext on an Enumerator. Perhaps two threads are trying to manipulate an object that is not inherently thread safe. Does your user have a dual processor PC? I spent days trying to track a similar problem that was only manifesting itself on a user who's PC was multi-processor. In addition you might want to attach to the Domain.UnhandledException event: AppDomain.CurrentDomain.UnhandledException +=new UnhandledExceptionEventHandler(CurrentDomain_Unhan dledException) It might be worth deploying the application's .PDB onto your user's PC to get additonal debug info Does the call stack give you any more usueful info? |
#4
| |||
| |||
|
#5
| |||
| |||
|
|
The .PDB can be deployed onto your users PC in the same folder as your release build. When you set the build to be a Release build you can also set Build | Generate Debugging Informaton to true to get it to create a debug file for your Release code (it's set to false by default). That way you'll get line numbers in your StackTrace. Note if you simply copy the PDB from your Debug build into your Release build folder they won't match and you'll not get the line numbers In terms of fixing the dual processor issue, I tidied up some poorly written multi-threading code which I'd inherited. That fixed it :-) |
#6
| |||
| |||
|
|
From the UI point of view it might be worth looking at the BackgroundWorker component in v2 of framework |
#7
| |||
| |||
|
|
Hi Randy, yep still here Yes enumerating through collections such as a Hashtable is NOT thread safe (even if it was created via the Synchronized wrapper method) Using a lock is what you need, but don't forget lock(this) will only lock on the current object (this), which I assume is a class that contains your Collection. You need to use lock(myCollection) assuming mycollecton is the collection variable that you're accessing If all else fails you could start with the greatest level of locking and work your away down. You can use the MethodImpl(MethodImplOptions.Synchronized) attribute at method level so that the method can only be executed by one thread at a time. That's the worse case situation though :-) From the UI point of view it might be worth looking at the BackgroundWorker component in v2 of framework |
#8
| |||
| |||
|
#9
| |||
| |||
|
|
Glad to help out. From multi-threading point of view it's even worse if you're adding/deleting from collections such as Hashtables. From the VS2003 Help "To support one or more writers, all operations on the Hashtable must be done through the wrapper returned by the Synchronized method" and adding/deleting are writing operations. Provided you serialise calls via the lock statement you should be safe. So yes you must use lock - again to you need to determine if lock(this) will give you enough scope or whether you need to use a locking variable. At one place I worked at last year I had a bizarre situation caused by poor multithreading. I had a breakpoint set on a Property Get and I was looking at a value, I looked away and looked back a few seconds later to find that the value had changed. This is because someone had used some code that checked for a null in the Property Get and if it was null it would go and create an instance of the returning variable and return that. Not only was this dangerous from a multi-threading point of view but it was a questionable oo design choice - blurring Property Gets/Sets. In that situation this is the sort of construct that I used (also works well with static members/value types): private object columnList_LockObject = new object(); private ColumnList columnList = null; public ColumnList Columns { get { if (columnList == null) { lock(columnList_LockObject) { if (columnList == null) { columnList = new ColumnList(); } } } return columnList; } set { columnList = value; } } I don't think it's that painful too implement effective locking. Yes it might be a bit slower, in terms of what the CLR has to do behind the scenes to give you locking, and with queuing the other threads up but it think it's a small price to pay for happy users :-) I'm going to be doing a lot more VS2005 starting in the next few weeks - I guess I'll be finding more a few of these issues popping up too |
![]() |
| Thread Tools | Search this Thread |
| Display Modes | |
| |