I am building an Windows Form-based app that listens on a port and when it receives a specific command, it opens a window (Form) that requests input.
My problem is that even though I am using a delegated method to open the window, only the window furniture/border is drawn. The contents of the form are not rendered at all.
From searching other answers on S.O., there seem to be two causes for this:
InitializeComponent() not being called
Trying to open the window from a non-UI thread
It appears that #2 is my problem. When I compare the ManagedThreadId in the form constructor and from the callback delegate, they are different.
As far as I can tell from the docs, the delegate should ensure that the callback is run on the UI thread.
Can anyone suggest why it isn't?
Below is a simplified version of what my code looks like.
The form
public wPrompt(bool silent, bool listen)
{
InitializeComponent();
// Thread.CurrentThread.ManagedThreadId returns 1
// Register a handler for scan requests received via the network
SocketListener.OpenFormRequest += OpenFormCommandHandler;
// Class that contains the code to open a socket and listen for commands
SocketListener.StartListening();
}
private void wPrompt_Load(object sender, System.EventArgs e)
{
// Thread.CurrentThread.ManagedThreadId returns 3
}
// The callback that gets called by the delegate
private void OpenFormCommandHandler()
{
// Thread.CurrentThread.ManagedThreadId returns 3
// Open the form
Visible = true;
}
The SocketListener class
class SocketListener
{
public delegate void OpenFormRequestEventHandler();
public static event OpenFormRequestEventHandler OpenFormRequest;
public static void StartListening()
{
// Thread.CurrentThread.ManagedThreadId returns 1
// Initialise and start worker thread
workerThread = new Thread(new ThreadStart(ListenThread));
workerThread.Start();
}
// A slightly modified version of the Synchronous Server Socket Example at
// https://learn.microsoft.com/en-us/dotnet/framework/network-programming/synchronous-server-socket-example
private static void ListenThread()
{
// Thread.CurrentThread.ManagedThreadId returns 3
// Opens socket and listens for command
if (/* command received */) {
OpenFormRequest?.Invoke();
}
}
}
The delegate callback function is run on the same thread as the socket listener. Not the UI thread as expected.
Can anyone explain what's happening please? I don't do a lot of .net development, so I am having trouble nutting this out.
As far as I can tell from the docs, the delegate should ensure that the callback is run on the UI thread. Can anyone suggest why it isn't?
There are no docs that should suggest that. I.e. it's not sufficient simply to use a delegate. You have to invoke the delegate using a mechanism that would move that invocation onto the UI thread, and there's nothing like that in the code you posted above. You seem to have misunderstood whatever it was that you read.
The issue with your code is that you appear to have confused the compiler-generated Invoke() method for a delegate with the framework-provided Control.Invoke() method. Your code calls the former, while you should be calling the latter. All that the former does is to actually invoke the delegate; the latter is what handles marshaling the execution of a delegate onto the UI thread so it can be executed there.
Frankly, it's a mistake for the socket-related code to try to address this at all. In the ListenThread() method, just raise the event normally (which ironically is the syntax you're using, so actually you don't need to change anything there). In your OpenFormCommandHandler() method, then you should call the Control.Invoke() method to execute whatever code you need to execute there, such as creating and showing a new form.
Based on your recent edit, in theory here is how you would change your event handler:
private void OpenFormCommandHandler()
{
// Thread.CurrentThread.ManagedThreadId returns 3
// Open the form
this.Invoke((MethodInvoker)(() => Visible = true;));
}
But I infer from your problem description that the form has not actually been shown once yet, which means it hasn't yet been tied to main thread and so Control.Invoke() is unlikely to work (you'd probably get an exception reporting that the window handle hadn't been created yet…I forget the exact wording, and it's not important enough for me to go looking it up right now).
Assuming that's the case, you need to get a synchronization context from elsewhere. Unfortunately, the question still lacks the specifics that would allow a more explicit answer showing exactly how to do that. But depending on what else is going on in your program, you could:
Pass a different Form instance to the wPrompt constructor and use that instance when calling Invoke(). Or,
Pass SynchronizationContext.Current to the wPrompt constructor, and call that object's Send() or Post() method (equivalent to Control.Invoke() and Control.BeginInvoke(), respectively).
There are other mechanisms you could use to capture and then use the synchronization context, but I'd say based on the details in your question, one of those two will be preferable to you.
Related
I have a winforms app. In development mode, when debugging from Visual Studio .NET 2003 (Yes, I know it's old, but this is a legacy project), I get this error when I try to open a new form. In order to open a new form I get an instance of the form and then I call ShowDialog() method, for example:
frmTest test = new frmTest(here my parameters);
test.ShowDialog();
If I press F11 (step into) when debugging it is not crashing, but If in the line where I instantiate the form I press F10 to go into next line, that is, test.ShowDialog(), then it crashes showing this error.
The complete message error is:
"An unhandled exception of type 'System.ApplicationException' occurred
in System.drawing.dll. Additional Information: An attempt was made to
free a mutual exclusion that does not belong to the process"
I have translated last part: Additional information ... since it was appearing in spanish.
The form that I am instantiating with parameters, its constructor, consists on initialize some variables for example:
public frmTest(string param1, string param2)
{
InitializeComponent();
this.param1 = param1;
this.param2 = param2;
}
private void frmTest_Load(object sender, EventArgs e)
{
// here I call a remote webservice asynchronously.
}
Also my form "frmTest" has four pictureboxes, a label, and a button. Three of the pictureboxes contain a png image (it is assigned on design time through Image property), the last picturebox contains a animated gif, also loaded in design time through Image property. Maybe the error occurs due to these images?
TL;DR: Your web request handler will execute on a different thread. Ensure you don't do anything that isn't thread-safe in that handler. You can use Invoke to dispatch your callback handler's code to the main thread.
Diagnosis
The problem here is almost certainly hiding in the missing details of your asynchronous call.
// here I call a remote webservice asynchronously.
Asynchronously is a little bit too vague to be sure what exactly is happening, but there's a very good chance that the asynchronous mechanism that you are using has executed its callback on a different thread from the main UI thread.
Overview
This is common in the .NET model. Asynchronous I/O in the .NET model makes use of threads in a thread pool to handle I/O via I/O Completion Ports (IOCP). It means that when a call like Socket.BeginReceive or WebRequest.BeginGetResponse (or any .NET asynchronous web request that uses similar technology internally) completes, the callback will execute on a thread in the thread pool, not the main thread. This may be surprising to you, since you didn't actively create another thread; you just participated in making asynchronous calls.
You must be very careful about what you do in the callback from your web request as many user-interface / Windows Forms operations are not permitted on any thread other than the main UI thread. Similarly, it may not be the UI itself that is causing you problems, you may have just accessed some resource or object that is not thread safe. Many seemingly innocuous things can cause a crash or exception if you're not careful with multithreading.
To resolve the issue:
If in doubt, in your callback, as early as you can, dispatch (a.k.a. Invoke) the code in your handler so that it runs on the main thread.
A common pattern for doing this would be something like what follows below.
Suppose you have made a call like this:
IAsyncResult result = (IAsyncResult myHttpWebRequest.BeginGetResponse(
new AsyncCallback(RespoCallback), myRequestState);
The handler might be set up like this:
private static void RespCallback(IAsyncResult asynchronousResult)
{
// THIS IS NOT GOING TO WORK BECAUSE WE ARE ON THE WRONG THREAD. e.g.:
this.label1.Text = "OK"; // BOOM! :(
}
Instead, dispatch any necessary processing back to the main thread.
private static void RespCallback(IAsyncResult asynchronousResult)
{
this.Invoke((MethodInvoker) delegate {
// This block of code will run on the main thread.
// It is safe to do UI things now. e.g.:
this.label1.Text = "OK"; // HOORAY! :)
});
}
I'm not advising this as a general best practice. I'm not saying to just immediately dispatch all your handlers back to the main thread. One size does not fit all. You should really look at the specific details of what you do in your handler and ensure you aren't doing thread-specific things. But I am saying that in the absence of any kind of explanation from you about what your asynchronous handlers are doing, the problem would likely be solved by invoking the handler code on the main thread.
Note: Of course, to fix your problem with this technique, it requires that your main thread is running. If you blocked your main thread with a (bad) technique like the one in this example then you'll have to redesign part of your app. Here's an example of something that would require a bigger rework:
// Start the asynchronous request.
IAsyncResult result=
(IAsyncResult) myHttpWebRequest.BeginGetResponse(new AsyncCallback(RespCallback),myRequestState);
// this line implements the timeout, if there is a timeout, the callback fires and the request becomes aborted
ThreadPool.RegisterWaitForSingleObject (result.AsyncWaitHandle, new WaitOrTimerCallback(TimeoutCallback), myHttpWebRequest, DefaultTimeout, true);
// The response came in the allowed time. The work processing will happen in the
// callback function.
allDone.WaitOne(); // *** DANGER: This blocks the main thread, the IO thread
// won't be able to dispatch any work to it via `invoke`
Notice the WaitOne call? That blocks execution of the executing thread. If this code executes on the main thread, then the main thread will be blocked until the WebRequest completes. You'll have to redesign so that either you don't block the main thread (my recommendation) or that you more closely examine your callback handler to see why what it's doing is conflicting with other threads.
Application exceptions are not thrown by the framework itself: what-is-applicationexception-for-in-net; Problem should be in the code you have not the framework. Also be sure to check "InvokeRequired" property before taking the action and if it is, run the method using "Invoke" method. Can check c-sharp-cross-thread-call-problem for that.
May be the async call is trying to access UI thread.
Make sure you are not using control properties like TextBox.Text. If so, you just have to pass its value to the async call, or store it in a class variable before the call.
Also, inside an async call you can't assign values to that properties. Use Invoke() instead.
Try to add an exception breakpoint and VS will stop at the instruction causing the exception. The actual stacktrace may help.
Have You tried to close VS's local variable watch window? Maybe it is evaluating something for You on UI components where the accessing thread should be equal to owner thread of UI component!
I have a class with a Socket, listens to clients to receive data. When receive new data I want to call an event (if implemented) but as you know every connection has its own thread so the event will run at that thread and you know the rest. you can not work with form controls.
How do I call the event (or invoke it). I'm really new to thread and network programing so I appreciate any example.
public class HVremotechooser
{
public delegate void NewOrder(Order order);
public event NewOrder nOrder;
//... (code elided)
public void ReceiveCallback(IAsyncResult AsyncCall) // new connection of client
{
//... (code elided)
if (nOrder != null)
nOrder(Order); // calling the event "nOrder"
//... (code elided)
}
}
thank you.
If you want to update your form from a non-UI thread, you have to invoke the action. What I normally do is the following:
private void LongRunningBackgroundThread() {
// lots of work
...
// Update my form
InvokeIfRequired(() => {
...update form...
}
}
private static void InvokeIfRequired(Action a) {
if (control.InvokeRequired) {
control.Invoke(a);
} else {
a();
}
}
See here and here
I ran into a similar problem with a Silverlight application that I was working on last week, and used the Dispatcher.BeginInvoke method. With Windows forms, it looks like it might be easier to use Control.BeginInvoke instead (although I believe that either should work): http://msdn.microsoft.com/en-us/library/system.windows.forms.control.begininvoke.aspx
You can use the typical marshling operations like Invoke or BeginInvoke to inject the execution of a delegate onto the UI thread. Just pass an instance of ISynchronizeInvoke or SynchronizationContext to your class to facilitate the marshaling.
However, I would not do that in your case. Since, presumably anyway, these callbacks are occuring because of socket events it is possible likely they are coming in hard and heavy. You definitely do not want to slam your UI thread with all of that activity. Instead, package up all of the pertinent data and put into a collection that the UI thread can then poll for using a System.Windows.Forms.Timer on a more reasonable interval.
I rip on these marshling operations all of the time. They are way overrated and overused. Remember, there are two general methods of sharing data and signaling between UI and worker threads.
Push method via Invoke or BeginInvoke in the worker thread
Pull method via System.Windows.Forms.Timer in the UI thread
The pull method can be, and often is, more elegant.
UI Threading is a UI concern. In my opinion you shouldn't worry about invoking to the ui thread in this code. Rather the consumer of the event should do the Invoke or whatever other threading stuff they happen to need to do. That way if the UI person needs to change their strategy (e.g. by using a timer) your non-UI related code wont need to change.
Sorry for long title, I don't know even the way on how to express the question
I'm using a library which run a callback from a different context from the main thread (is a C Library), I created the callback in C# and when gets called I would like to just raise an event.
However because I don't know what will be inside the event, I would like to find a way to invoke the method without the problem of locks and so on (otherwise the third party user will have to handle this inside the event, very ugly)
Are there any way to do this?
I can be totally on the wrong way but I'm thinking about winforms way to handle different threads (the .Invoke thing)
Otherwise I can send a message to the message loop of the window, but I don't know a lot about message passing and if I can send "custom" messages like this
Example:
private uint lgLcdOnConfigureCB(int connection, System.IntPtr pContext)
{
OnConfigure(EventArgs.Empty);
return 0U;
}
this callback is called from another program which I don't have control over, I would like to run OnConfigure method in the main thread (the one that handles my winform), how to do it?
Or in other words, I would like to run OnConfigure without the need of thinking about locks
Edit 1:
I have a problem with this exception:
CallbackOnCollectedDelegate retrived
Message: Callback run on delegate 'G19dotNet!G19dotNet.LgLcd+lgLcdOnSoftButtonsCB::Invoke' collected in GarbageCollector. During unmanaged code delegates should be ensured will never be deleted until you are sure they will never be called
Edit 2:
Issue resolved by myself, thanks to Stackoverflow which always helps me!
For future reference: Defining a delegate as a function pointer
If you're using WinForms and you want to execute something on the UI thread, you need to call either Invoke or BeginInvoke on some control (be it a Button or a Form or whatever) that was created on that thread. You'll need a reference to it in order to do this.
For example, with your code and assuming that you have a reference to a form called form:
private uint lgLcdOnConfigureCB(int connection, System.IntPtr pContext)
{
form.Invoke(new MethodInvoker(() => OnConfigure(EventArgs.Empty)));
return 0U;
}
Before you call the 3rd party function, get a reference to Dispatcher.CurrentDispatcher. In the callback function, use dispatcher.Invoke.
What you end up with will look something like this:
class MyClass
{
private Dispatcher dispatcher;
public void runThirdParty()
{
this.dispatcher = Dispatcher.CurrentDispatcher;
callThirdPartyFunction(myCallBack);
}
public void myCallBack()
{
this.dispatcher.Invoke(new Action(() =>
{
//code to run here.
}));
}
}
There is a pattern for this called Event-based Asynchronous Pattern. The article linked is a great overview on how to use it. The AsyncOperation class is the key to this pattern.
This pattern might not fit perfectly with your problem that you are trying to solve, but it might give you some insights into the problem.
Thanks to Adam Robinson answer, I added a nice little utility function on my form:
private void runOnUIThread(Action function)
{
this.Invoke(new MethodInvoker(function));
}
And I'm using it like this:
runOnUIThread(() =>
{
example_lbl_status.Text = "Active";
});
I'm using the following method to show a modeless Message Box.
public void ShowMessageBox(string Message)
{
var thread = new Thread(
() =>
{
MessageBox.Show(Message);
});
thread.Start();
}
The "() => {...}" is something I've never seen before. What is the name for this code pattern?
Also, thread.Start starts the thread, and it automatically closes once the "()=>{...}" method completes (when the Message Box is OK'ed), right? If so, can you please point me to some official documentation saying that the thread closes automatically?
Thanks!
It's the lambda operator, and read as "goes to". MSDN has a good intro: Lambda Expressions (C# Programming Guide)
One concern with your example is that you're spinning up a new thread to update the UI, the UI is intrinsically single-threaded, so background updates are generally the wrong thing to do (unless you're manually/explicitly checking InvokeRequired and calling Invoke() as needed.
Regarding the UI threading...
In WinForms every Form or Control is created on a particular thread (the "UI Thread"), and you can think of that thread as owning that control (not exactly correct, but a good way to conceptualize it). Updating the UI from that thread is safe, updating the UI from another thread runs the risk of collisions and corruption and all the usual risks of parallel/async programming.
...So... how do you safely update the UI from a background thread without blocking the UI? In short--you can't--the best you can do is block it for the bare minimum required to update the UI. This is where InvokeRequired and Invoke() come in...
Here's a sample: you should be able to drop this into the code-behind of a new form with a button and textbox.
To use:
Try commenting out either the call to SetTextAsyncSafe() or SetTextAsyncSafe() -- running both could confuse you since they won't necessarily execute in the order they're called (they're running async, remember?).
Then set a breakpoint on SetText(). You should see the "safe" call will actually call the method twice--the first call will detect InvokeRequired and will call the method a 2nd time for the correct thread by Invoke()'ing to it.
You should see an Exception thrown when SetTextAsyncUnsafe() actually gets to the textBox1.Text = value; statements. The exception will be an InvalidOperationException with a message stating "Cross-thread operation not valid" -- you can google this term for more details.
The code:
private void button1_Click(object sender, EventArgs e)
{
SetTextAsyncSafe("This update was made from the UI Thread by using Invoke()");
SetTextAsyncUnsafe("This update was made directly from the background thread and can cause problems");
}
private void SetTextAsyncUnsafe(string value)
{
new Thread(() => SetText(value, false)).Start();
}
private void SetTextAsyncSafe(string value)
{
new Thread(() => SetText(value, true)).Start();
}
private void SetText(string value, bool checkInvokeRequired)
{
if (checkInvokeRequired)
{
if (InvokeRequired)
{
Invoke(new Action(() => SetText(value, checkInvokeRequired)));
return; // early exit
}
}
textBox1.Text = value;
}
That is a Lambda. In this case, you're using it to create a new anonymous method that will be run when the new Thread is started.
It's the (near) equivalent of:
public void ShowMessageBox(string Message)
{
var thread = new Thread(ShowBox);
thread.Start(Message);
}
public void ShowBox(object message)
{
MessageBox.Show(message.ToString());
}
This is called a Lambda Expression. You can read more here.
Lambda expression, C# version 3 feature.
Don't use this code. A message box needs a parent window, something it can make sure to be on top of. It can normally find a parent by itself by iterating the windows that were created on the same thread. Not in this case though, there are no other windows, it has to pick the desktop window as the parent.
That will go wrong badly when the user is working in an app window or switches focus to another app, the message box disappears behind the foreground window. There is no obvious way for the user to tell that it is there, she'll just loses sight of it. It could be hours, if not days, before she finds it back. That thread is meanwhile consuming resources badly, you would probably never consider it if you knew that this message box requires a megabyte of memory. In extreme cases, you'll crash the program with OOM.
The common alternative in Windows UI programming is a balloon tooltip provided by a NotifyIcon. Or your own form with the TopMost property set to True so it cannot easily get lost. Also allows you to control the position, important for "non-modal" notifications that should not get in the way. Set that form's ShowWithoutActivation property to true in the form constructor so it doesn't steal the focus.
Its a statement lambda.
Yes, thread is active as long as this anonymous method is running. Since after MessageBox.Show() there is no other statements, thread will exit, and this must be true... if you are in doubt add this before start:
thread.Name = "LALALA";
And then debug your app. When the message box apear, pause execution, go to Threads View and you will see LALALA running. Click OK and pause again, there should be no "LALALA"... =)
I've inherited code where BeginInvoke is called from the main thread (not a background thread, which is usually the pattern). I am trying to understand what it actually does in this scenario.
Does the method being called in the BeginInvoke get in line of messages that come down to the window? The docs say asynchronously, so that is my assumption.
How does the framework prioritize when to kick off the method called by BeginInvoke?
Edit: The code looks like this:
System.Action<bool> finalizeUI = delegate(bool open)
{
try
{
// do somewhat time consuming stuff
}
finally
{
Cursor.Current = Cursors.Default;
}
};
Cursor.Current = Cursors.WaitCursor;
BeginInvoke(finalizeUI, true);
This is happening in the Form_Load event.
edit
Now that we see the code, it's clear that this is just a way to move some initialization out of Form_Load but still have it happen before the user can interact with the form.
The call to BeginInvoke is inside Form_load, and is not called on another object, so this is a call to Form.BeginInvoke. So what's happening is this.
Form_Load passes a delegate to Form.BeginInvoke, this puts a message in the form's message queue that is ahead of all user input messages. It sets the cursor to a wait cursor.
Form_Load returns, and the rest of form initialization is allowed to complete, the form most likely becomes visible at this point.
Once the code falls into the message pump, the first thing is sees in the queue is the delegate, so it runs that.
as the delegate completes, it changes the cursor back to the normal cursor, and returns
profit!
original post below
I depends on the object that you call BeginInvoke on. If the object is derived from Control then Control.BeginInvoke will run on the thread that created the control. See JaredPar's answer.
But there is another pattern for the use of BeginInvoke. if the object is a delegate, then BeginInvoke runs the callback on a separate thread, one that may be created specifically for that purpose.
public class Foo
{
...
public Object Bar(object arg)
{
// this function will run on a separate thread.
}
}
...
// this delegate is used to Invoke Bar on Foo in separate thread, this must
// take the same arguments and return the same value as the Bar method of Foo
public delegate object FooBarCaller (object arg);
...
// call this on the main thread to invoke Foo.Bar on a background thread
//
public IAsyncResult BeginFooBar(AsyncCallback callback, object arg)
{
Foo foo = new Foo();
FooBarCaller caller = new FooBarCaller (foo.Bar);
return caller.BeginInvoke (arg);
}
This pattern is one reason that BeginInvoke is called from the main thread rather than from a background thread.
In the case BeginInvoke is called on a UI thread it will still go through the process of posting a Windows Message to the message queue where the message will wait to be processed. The delegate will run when the message is processed. This message is not prioritized in any way that's different than it being called from the background thread.
In this scenario I suspect the call looks like:
private void Button1_Click(object sender, ButtonClickEventArgs e)
{
Control.BeginInvoke(new MethodInvoker(()=> /* code etc. */));
}
What's happening is that some code will run on on a threadpool thread, and update the control on the thread that created the control whereas if Control.Invoke was used, some code would run on the thread that created the control, and update the control on that thread as well.
Prior to widespread BackgroundWorker use, you had to synchronize back to the UI thread before doing any operations on Controls created on the UI thread (i.e. pretty much every Control).
There's a pretty good reference example here down in the "Thread-Safe Calls to a Windows Forms Control" section.