I have a collection, which uses BindingOperations.EnableCollectionSynchronization. This works great for updating a collection on a background thread using the BackgroundWorker class; however, if the collection is in the process of updating, none of the items properties can be changed elsewhere until the worker has stopped (or so it appears).
The application ends up crashing and I assume this is because only one thread may have access to an object at any given time. If this is correct, how can I prevent the application from crashing?
The issue isn't accessing the collection on the background thread, it's allowing access elsewhere in main thread while collection is updating on background thread.
As a side topic, when I do multithread with my ViewModels I usually make sure my VM is thread safe or won't be broken by my code. And I fire all notifications change myself in the UI thread using Dispatcher.BeginInvoke()
In the case of a collection you might want to write your own "ThreadObservableCollection"
Since I can't see your code or debug it, I can only offer tips.
1. Objects that are instanced and shared are not thread safe. Static code is thread safe. If multiple threads are going to access the same code base, then make that shared "code base" static, if possible.
2. I don't use BGW anymore, if I can help it. I use the Task Parallel Library (TPL -- Google search it). This has saved me from insanity, multiple times.
Is this a possible scenario to use Ansyc programming here?
The closest to an ObservableCollection I could find was ConcurrentBag, but it doesn't seem to meet all my needs. By 'updating' I simply mean I'm adding items to it on a background thread. Ultimately, I found there is no issue changing the properties of items contained in the collection while items are being added with the current setup; however, the application crashes regardless if items are being added to it when a property in my view model changes, which I don't think has anything to do with threading now.
I'm going to implement my own thread-safe ObservableCollection class just to be safe and go from there. Thanks to everyone who responded!
The problem was in the unmanaged DLL. But I really learnt a great deal about other topics such as BackgroundWorkers and TPL. Thanks all.
Hello There. I have this small DLL that takes input_name and output_name as parameters. It opens the input file, reads it and produces output file with the specified name after some processing.
I then call this function from C#. First time I call it, it runs fine. But second time around, it throws this exception
An unhandled exception of System.AccessViolationException occured in CSharpProgram.exe.<br />
Attempted to read or write protected memory.<br />
Here is what I am trying.
[DllImport("MyDll.dll", CallingConvention = CallingConvention.Cdecl)]
publicstaticexternint Call_Dll_Main(string input, string output);
privatevoid Button_Click(object sender, EventArgs ea)
new System.Threading.Thread(new System.Threading.ThreadStart(Call_Dll_Function)).Start()
int nResult = Call_Dll_Main(txtInputFile.Text.Trim(), txtOutputFile.Text.Trim()); // HERE EXCEPTION COMES...FIRST TIME FINE...IT COMES SECOND TIME I CLICK THE BUTTON
What could be wrong? What am I missing here? Thanks for any input.
Well, the first thing I would do is put those TextBox values you trim into variables before you pass them to the .DLL. The GC will collect those values since they don't have any managed variables or pins holding onto references to them so the GC may be collecting them before your DLL code is finished with them.
Next, it would appear that you're completely ignoring the return code from the C function. I t has nothing to do with the error, but it's something to watch out for.
Any other problems would be in the C code itself, which you didn't show for this function.
I'm assuming you are using WinForms and those textXXXFile objects are Controls, maybe TextBoxes. A Control should only be created and used by a single thread, most often that would be the main or "GUI thread"; violating this rule is bound to give you AccessViolation trouble.
I would recommend you use one (or more if you think you must) BackgroundWorker objects ibstead of bare Threads. A BGW will execute most of its task on a separate thread (which it borrows from the ThreadPool), however it also offers progress and completion events which execute on the main thread (assuming you created the BGW on the main thread) so all AccessViolations would disappear.
If you're unfamiliar with the BGW class, read up on it, I'm pretty sure CP has some fine articles about it.
Note 1: you should get the inputfile before entering the DoWork event.
Note 2: you could reuse the BGW object, or create a new one, that is up to you.
Note 3: there are some BGW properties you have to set true explicitly for it to activate all its goodies!
pass the textbox values as parameters to Call_Dll_Function(). Remember that your thread can't access the controls from the UI thread - can't cross the streams.
I personally would use the Task Parallel Library (TPL) for this. There are articles on this here at Codeproject. Check it out (Sacha Barber has some good ones). I use TPL often. Task Parallel Library: 1 of n[^]
Such Access Violation Exceptions often mean that a pointer pointed to some location which is outside of the process space of your program. And such things are more likely to happen in unmanaged code, i.e. the C dll.
As we do not see the code of that dll, we can only speculate. It could be possible that the code tries to do something at the memory location of the strings it was passed at the first call, but Garbage Collection has removed them meanwhile.
The message is pretty explicit: it even tells you which process is holding the file open. So, if that is your app, then start looking through your code to find out where you open it, but don't close it again. We can't do that for you - we don't have access to your code!
Bad command or file name. Bad, bad command! Sit! Stay! Staaaay...