Legacy application creates dialogs in non-ui thread
I've been working support for a while on a legacy application and I've noticed a bit of a problem. The system is an incredibly complex client/server with standard and custom frameworks.
One of the custom frameworks built into the application involves validating workflow actions. It finds potential errors, separates them into warnings and errors, and passes the results back to the client. The main difference between warnings and errors is that warnings ask the user if they wish to ignore the error.
The issue I have is that the dialog for this prompt is created on a non-ui thread, and thus we get cross-threading issues when the dialog is shown. I have attempted to invoke the showing of the dialog, however this fails because the window handle has not been created. (InvokeRequired returns false, which I assume in this case means it cannot find a decent handle in its parent tree, rather than that it doesn't require it.)
Does anyone have any suggestions for how I can create this dialog and get the UI thread t开发者_如何学Pythono set it up and call it?
I am not entirely clear on the details of your implementation but the below code is how you would handle marshalling a call from you're non-ui thread to the ui thread. This code snippet assumes that the "this" object is a windows form and represents the ui thread.
The idea is that your non-ui thread calls the method named "ShowMessageBox", which resides on the ui-thread. When the call happens you check the this.InvokeRequired from an object on the ui-thread, which in this example would be a windows form. The InvokeRequired would return "true" which would cause the code in the first part of the if statement to be executed. This code invokes a call back to the ShowMessageBox function from the main ui-thread by creating a delegate of the same signature as the "ShowMessageBox" method and re-passing the sender object and event args, in effect marshalling the non-ui thread call to the ui-thread. This subsequent call to the “ShowMessageBox” method is now "marshaled" to the ui-thread and will bypass the first part of the if and move to the else where you can call the messagebox or form or whatever you need to.
Enjoy!
private object _lock = new object(); //should have class scope
private void ShowMessageBox(object sender, EventArgs e)
{
if (this.InvokeRequired)
{
lock (_lock)
{
EventHandler d = new EventHandler(ShowMessageBox);
this.Invoke(d, new object[] { sender, e });
return;
}
}
else
{
MessageBox.Show("Show some messsage or invoke your form instance.");
}
}
After create your control. Force it to create handle by accessing it's handle property:
sync = new System.Windows.Forms.Control();
var temp = sync.Handle;
And then you are good to go to invoke it:
sync.Invoke((Action)(() => { }));
精彩评论