问题
My application (C#, VS2008) loads information from a database (SQL Server 2008 Express) over the network. During (possibly) longish waits, I want to have a 'Loading...' dialog box appear running on a different thread, but only if the operation takes more than a specific time period (say 500ms).
So, I have so far got my loading form being displayed after 500ms (if the operation lasts that long) without setting the loading dialog form's owner (i.e calling LoadingDialog.ShowDialog()), but when I try to call LoadingDialog.ShowDialog(IWin32Window owner) with owner set to the main form (passed in through the thread's parameter) I get the InvalidOperationException about accessing controls across threads.
My basic question is: Can I create and ShowDialog a form with the owner parameter set to a form on another thread? I want to do this so that the loading dialog is modal the rest of the application, i.e. like any other dialog takes the focus and disallows input elsewhere.
Can anyone offer a suggestion? I have read heaps about splash screens with no luck, also about Invoke and BeginInvoke with no luck. Is there a different way I should go about this?
Please feel free to ask for clarification if you don't understand.
Merci (as they say in French),
Jacob.
回答1:
You should run your long process in a background thread, and then show your Loading... form as a non-modal dialog. That way, the user can see the Loading indication, but still interact with other parts of the system while its going on.
Another option would be to show the loading progress in a status bar or similar. The key is to make sure the long operation is done on a background thread and all the GUI logic is done on the GUI thread.
A good threading format might look like (this is just pseudocode for demonstration purposes - you need to use Invoke to get the appropriate threading):
RunInBackground(DoLongOperation);
ShowLoadingDialog();
...
DoLongOperation()
{
LongOperation();
RunOnGUI(FinishLongOperation);
}
FinishLongOperation()
{
CloseLoadingDialog();
}
回答2:
All the UI components run on single sole thread which runs over the win32 message loop. You can not run any UI component in another thread. This architecture persists since Windows 3.1.
回答3:
You CAN create as many UI threads as you want. The following code should do the trick:
Thread thread = new Thread(new ThreadStart(() => Application.Run(new MyForm())));
thread.SetApartmentState(ApartmentState.STA);
thread.IsBackground = true;
thread.Start();
来源:https://stackoverflow.com/questions/1660867/setting-form-owner-to-a-form-from-a-different-thread