I have an application in which I am running a separate thread.
Dim thread As New System.Threading.Thread(AddressOf Main)
thread.Start()
However, the thread makes reference to an textbox named Output, and it generates this error upon execution:
System.InvalidOperationException was unhandled
Message="Cross-thread operation not valid: Control 'Output' accessed from a thread other than the thread it was created on."
Source="System.Windows.Forms"
(message shortened for space)
How can I make the operations run on another thread, but still use the Output object? I cannot call a subroutine to do that for me, as it generates the exact same error.
The method called is AppendText, by the way.
I am probably missing something important here, so thanks for the help!
Instead of just calling the AppendText method you need to force it to execute on the correct thread. So, if you have a call like this:
myTextBox.AppendText("some text")
...you need to change it to this:
myTextBox.BeginInvoke(New Action(Of String)(AddressOf myTextBox.AppendText), "some text")
You can use either Invoke or BeginInvoke. In this case, since AppendText doesn't have any return value, BeginInvoke is a good choice (the difference is that Invoke will block the current thread while the GUI thread executes the AppendText method, while BeginInvoke will make the call asynchronously instead).
You should use Control.Invoke or Control.BeginInvoke to call your subroutine.
This exception is a very popular exception when using a thread.Some operation are not thread safe (like accessing a control on a thread other than its own thread) so framework is preventing these kind of problems.
To solve it you can either use Control.Invoke method to call a delegate that is in the same thread the control or you can use a background worker.
Here you can find a sample of first approach
and
Here you can find a sample of a background worker
Related
I have a static object that needs to initialize an imaging API. The allocated resources of this imaging API need to be released by the same thread.
So I'm starting a thread in my static object that initializes everything and then waits for a counter to reach zero. When this happens the thread cleans all up and finishes.
This is an unmanaged class inside a managed library, so I can't use System::Threading::Thread (needs a managed static member function) or std::thread (compiler error, not supported with /clr).
So I have to start my thread like:
CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)&Initialize, this, 0, 0);
All works fine, the init is done and the API functions work. But when I close the application I see that the usage counter of my static object reaches zero but the clean up function is never called by the thread, as if the thread was killed. Is there a way to make sure the thread will continue to exist and execute until its end?
After turning this around in all possible ways and adding events etc I guess this is not possible so I'll have to change the structure of my code and encapsulate the non managed class inside a managed class, and add the thread to the managed class.
I think you could proceed in one of two ways:
Wrap the resources in RAII-style classes, and refactor to have the objects' lifetimes be on the stack of your created thread, ensuring their destructors get called when the thread loop exits without having to call any additional cleanup. If there is no issue with the thread returning correctly when your counter reaches 0, this should be the simplest and cleanest way of addressing this.
I'm thinking you could intercept the WM_CLOSE message using window procedures, process necessary cleanup and then pass the message on, effectively "stalling" it until you are ready to close. Note that even though you are in a DLL you can still set up a window procedure and message pump system, you don't need a GUI to do that. I am however not 100% sure on whether you'll receive the WM_CLOSE message that concerns the application that "owns" your DLL, it's not something I've tried out yet.
You will have to implement some form of messaging through events within your thread's loop however, as the WindowProc will be called on a different thread, so you know when to call the cleanup procedure.
I also am not very familiar with CLR, so there might be a simpler way of interacting with those APIs than with raw C++ calls and handles.
I know you can't call a GUI update function from a background thread, yet I can't see how creating a delegate, assigning the GUI update function to it, and then calling it solves this problem. How is this any different than calling the GUI update function itself? How does creating a function pointer (delegate) solve this problem?
Delegates do not solve this problem, the Control.BeginInvoke() or Dispatcher.BeginInvoke() methods do. Only they know how to properly run code on a specific other thread, a feature provided by the message loop (aka dispatcher loop) that the UI thread uses. Such a loop is the common solution to the producer-consumer problem.
These methods require a delegate object, passed as an argument. So that they know what specific code needs to run on the UI thread.
I am interfacing an instrument that sends data via IP. I want to put my reading code in a timer to read the data in the background while the user interacts with the program. My problem is that it appears streamreader readline blocks. Is that true? If so how should I go about reading a line from the input device with out blocking?
I should also note my streamreader is a Networkstream. Also the target framework is Net 2.0. Not sure if that is important or not.
TIA,
John
StreamReader.ReadLine is a blocking (synchronous) method. When you call it, it will block execution from continuing until a complete line has been received. That makes it much easier to work with, but obviously, if you need it to work asynchronously, it doesn't meet your needs.
The StreamReader contains both blocking and asynchronous versions of many of it's methods. For instance, in addition to the ReadLine method, there is also a ReadLineAsync method which does the same thing as ReadLine, but it does so asynchronously.
So, the choice you have is, either you need to use one of the asynchronous methods, or you can continue to use the ReadLine method, even though it is a blocking method, as long as you call it from another thread. If it blocks a background thread, whose sole purpose is to read the stream, that doesn't really matter to you, as long as the UI thread isn't blocked. So for instance, you could have a method like this:
Private Sub MonitorStream
While True
ProcessLine(_Reader.ReadLine)
End While
End Sub
Then, you can call that method in a new thread, like this:
Dim t As New Thread(AddressOf MonitorStream)
t.Start()
That's just a simple example. You'd probably want to check if the stream is open rather than just looping infinitely, etc. But that should give you a starting point. I'd say that using the ReadLineAsync method would probably be preferable, but for someone who is knew to asynchronous programming, the infinite loop in a separate thread is easier to work with and understand.
It's easy to do so in objective c but I do not know how to do so in vb.net
update:
I know about control.invoke. But control.invoke requires a control that may change from program to program. What would be the easier way?
So yes program is winform. However I need a solution that does not depend on any specific control. If that's the case actually I do not need things to be run on main thread do I?
What do you mean by "ensure". Do you want to be able to check from the running thread if it is on the main thread or do you want to programatically say before code is actually run that it must only run on the main thread.
Are you trying to update the UI from a secondary thread? If so, there are usually better ways (depending on the application type) to do that than checking the thread itself. For instance, in a WinForms app you can actually safely ask most controls if a cross thread call is needed by checking the InvokeRequired. If true then you can pass the control a Delegate to run your code which will put it on the main UI thread for you.
No body does this right. So I did the only way I know. Have a global variable and synchronize that global variable. It doesn't guarantee that the thread will run at the same UI thread. However, it guarantee that the codes won't run simultaneously. Which is what I want.
Is there a way for me to hook the exit of managed threads (i.e. run some code on a thread, just before it exits?)
I've developed a mechanism for hooking thread exit that works for some threads. Step 1: develop a 'hook' STA COM class that takes a callback function and calls it in its destructor. Step 2: create a ThreadStatic instance of this object on the thread I want to hook, and pass the object a managed delegate converted to an unmanaged function pointer. The delegate then gets called on thread exit (since the CLR calls IUnknown::Release on all STA COM RCWs as part of thread exit).
This mechanism works on, for example, worker threads that I create in code using the Thread class.
However, it doesn't seem to work for the application's main thread (be it a console or windows app). The 'hook' COM object seems to be deleted too late in the shutdown process and the attempt to call the delegate fails.
(The reason I want to implement this facility is so I can run some native COM code on the exiting thread that works with STA COM objects that were created on the thread, before it's 'too late' (i.e. before the thread has exited, and it's no longer possible to work with STA COM objects on that thread.))
Do you control thread creation? It's probably simplest to simply wrap the thread's code in a try...finally clause, and put your code in the finally.
Note that when the AppDomain shuts down, you can never be sure that your code will be called since the shutdown may be less than graceful.
When you say "Destructor" I presume you mean a C++/CLI destructor - i.e. the .Dispose() method?
If you need to support hooking before the process exits, you could try the AppDomain.CurrentDomain.ProcessExit event - which doesn't seem to fire on an unhandled exception, or AppDomain.CurrentDomain.UnhandledException which seems to fire only on an unhandled exception.
None of this looks particularly robust, mind you...