Coded UI method in separate thread - c#

I have wrote a little application which can determine different properties of a control.
I use Coded UI methods.
So i have got a GUI where the control information's appeared.
I determine the control via the position of it.
UITestControl control = UITestControlFactory.FromPoint(new Point(X, Y));
After that, i ask the control specific properties with reflection.
All methods take about 5 second.
I would like to appear a loader message/control/window while computing in progress.
I found a suitable solution to it, i use BusyIndicator from Extended WPF Toolkit library.
I try to use Background worker class to implement my demand, but i get the next exception:
"The Coded UI Test is running in Single Thread Apartment (STA) mode of COM. In this mode, all the playback calls should happen from the TestMethod thread only and UITestControl should not be shared across TestMethods."
My answer for it: OK.
I try an other idea.
I use parametrized thread, where i set the state for apartment to STA, because of the above exception.
Thread thread = new Thread(new ParameterizedThreadStart(*CODED_UI_SEARCH_METHOD*));
thread.SetApartmentState(ApartmentState.STA);
thread.Start(Object object);
But after of it, i got the same message against my set thread.
So, my question: how can i solve to run the identifying of control in an other thread while a message window/control inform the user about the process?
Thanks in advance.

Related

Background worker issue

i have a class which, when a certain part of the gui is clicked will
-create a backgroundworker and do the following taks
-create a new object(this is a new windows form)
-call a method on it which gets some data
-populate the new windows form gui with that data
The problem is there is a gui component on the form which cant be created from outside of the main programme thread, if i do try i get the error
Active x .... cannot be instantiated because the
current thread is not in a
single-threaded apartment.
is there help people can offer so i can structure this?
in my do work
Don't create GUI components in a background thread. Use the background thread to get and process data, then render them in the UI in the main thread. I know that this in inconvenient, because
creating lots of UI elements can also take a lot of time and
creating them in the UI thread requires you to split your code into UI part and data processing part,
but there's not really a way around it. .NET UI components are not designed to be handled in background threads.
To perform only certain operations of your code in the main thread, you can use
someUIControl.Invoke(...) (WinForms) or
Dispatcher.Invoke(...) (WPF)
in the DoWork event handler of your BackgroundWorker. Alternatively, you can perform the UI operations in the RunWorkerCompleted event handler of your BackgroundWorker, which always executes in the UI thread.
The UI should only be managed by the UI thread.
One possible solution would be to load the data asynchronously with the BackgroundWorker, and when it is done use the Result property of the DoWorkEventArgs to pass the results back to the UI thread and then display the new form.

Open InternetExplorer COM object to do some automation using Wating from WPF app, but keep UI responsive. is this possible?

I have an app that runs a process which needs to open an internet explorer, go to an url, and do some stuff there, input some data, and return.
This usually takes a while (several pages that need to be filled, doesn't matter). The problem is, while this process is being done, the calling app (a standard wpf app) UI is unresponsive/frozen. When the process returns, i have some info that i need to set in one of the WPF app's objects
The main problem is that since IE needs to be called from within an STA thread, if I try to call it from within the dispatcher asynchronously or synchronously, for some reason the UI is blocked (i have tried with different DispatcherPriority-es but didn't get lucky).
If i start a new BackgroundWorker, that thread is in MTA mode (and i can't switch it back), so there's a problem and i have an exception
I'm really lost here, could anyone put some light into this? maybe what i want to do is simply not possible.
Have you tried creating your own background thread (not relying on BackgroundWorker), and set its ApartmentState to STA?

How to show progress status for a long-time-consuming function?

I have a windows form simply like this: 1) a button when clicked will perform an operation taking a long time to complete, 2) a label showing how much percentage of the progress is going on.
In the long operation I mentioned, I write the code to update the Text property of the label but it doesn't work!
Please help me to show the progress status correctly.
You can take a look at the BackgroundWorker class (see the MSDN overview). It allows you to run some long-running operation in background and report progress updates (percentage) and completion from the background task to the user interface. Note that you'll need to calculate the progress percentage yourself.
However, the BackgroundWorker class takes care of other tricky aspects, such as sending your progress reports to the main GUI thread (where you can safely update the user interface).
Your going to want to create a worker thread that performs the task and occasionally reports its update to the form thread. If you do all of your work in the UI thread, your UI will be locked and won't update the progress/label correctly.
Before you start the worker thread, calculate the total number of steps you believe the process will take. Start the worker thread. After each unit of work, you Invoke an update method on the UI thread to increment the process.
You'll want to look at the BackgroundWorker class.
If your application will have several of these, I recommend creating a process interface (e.g. IProgressProcess). This interface will contain methods for executing a process and reporting updates. You will create all of your process classes by implementing from this interface. Write a control that contains a progress bar and accepts an IProgressProcess through a constructor or property. It can then use your custom process to execute and move along the progress bar. Then you can have your custom progress control send events when the process is complete or canceled.
This usually happens if you try to update the UI on the same thread where the operation is occurring. There are a couple of different ways that you could accomplish this.
You can update the UI with the BeginInvoke method.
You can use a BackgroundWorker component.
The reason that you don't see any change, is that the change causes a message to redraw the label, but the main thread is busy working so it doesn't respond to the message.
The simplest solution would be to just call the Application.DoEvents after updating the label. That works as a quick fix for your immediate problem, but it still will leave the application unresponsive in any other way.
The good solution would to start the operation in a separate thread. That way your main thread is free to handle messages while the operation is running. However working in a separate thread means a litte more work when communicating with the UI. If you want to update controls, you have to use the Invoke method to start a method that runs in the main thread so that it has access to the controls. Alternatively you can just update a variable in the thread, and have a timer control that periodically checks for changes in the variable and updates the label accordingly.

Setting Form.Owner to a form from a different thread

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.
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();
}
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.
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();

Use the UI thread of a WPF application to do a long processing task on a UI element, but also update a progress bar on the same window

My program consists of a large graphing UI control that I need to spend about 15 seconds re-loading every once in a while. Because the updating code works primarily with the UI control (maybe 90% of it actually sets properties on the control), it would make sense to me to actually let the UI thread handle that. I really don't want the control to visually re-paint while it is loading in a separate thread from the UI.
I also want a progress bar to update as well that lives in the status bar of the same application window. Is there a way to break the rule in this case and re-paint only the progress bar, or should I just open a new application window for the progress bar to live in?
What would you do in this particular case?
If you can break your primary task (ie. updating the graph) in many steps, you can perform each step as a separate dispatcher message. This will allow other messages to be processed, including giving you the ability to update progress information.
The basic pattern is:
Invoke your primary task, passing in zero for the step.
Perform the step.
If there are more steps, queue another message, passing in step + 1.
You can then add in progress updates at the appropriate points in your code.
PS. Not saying this is your best option - hard to tell without knowing all the details. But this is an option.
It is not really true that there is only one UI thread in an application, it is just that most windows applications only ever create UI objects in one thread so this thread becomes "the" UI thread in the application. It is easy to understand why - this makes the code simpler to understand, and protects us from implicit thread binding issues between controls.
This suggests a possible idea, should it prove impossible to improve the speed of updating the control (which is what I would suggest to do first). Create the UI control on a separate thread. You need to make sure that the thread is suitable for UI, that is to say the threading model is STA, and that it will pump messages and not die before the control is destroyed. I don't know if you need to create the parent window in the UI thread as well, or just the control but it may be worth experimenting here.
Find a graphing UI control that is more efficient. Unless the UI thread yields to the message loop any other updates won't happen (and it will slow down your graph control's updates).
I would suggest using a progressbar in a new window (without the form headers). Make it paint the progress bar by reading the shared properties of a graph control. this way you can avoid the thread blocking (sluggish loading).. And it gives you good visual experience (progressive painting on both the controls).

Categories

Resources