STA threading

Ask general questions here.
atom
Posts: 357
Joined: Sun Dec 07, 2008 11:14 pm
Location: Dublin, Ireland

STA threading

Post by atom » Fri Jul 24, 2009 11:40 am

Hiya

In my framework I have 2 threads:
- Test Case Thread
- BackgroundWorker thread

The background worker component never uses Ranorex function, but uses windows API instead.
In the Main() function ive put [STAThread]
However In the ranorex log i get:

"The apartment state of the current thread is not set to STA. Please make sure that all threads accessing Ranorex methods have their apartment state set to STA."

And some Ranorex method cause a crash.

Can you advise please

Thanks

atom
Posts: 357
Joined: Sun Dec 07, 2008 11:14 pm
Location: Dublin, Ireland

Re: STA threading

Post by atom » Fri Jul 24, 2009 12:04 pm

actually the problem comes from our AUT
The Spy Tool crashes when pointed at a certain window

Can I raise a support issue for this?

User avatar
Support Team
Site Admin
Site Admin
Posts: 12145
Joined: Fri Jul 07, 2006 4:30 pm
Location: Houston, Texas, USA
Contact:

Re: STA threading

Post by Support Team » Tue Jul 28, 2009 3:47 pm

atom wrote:Can I raise a support issue for this?
Thank you for reporting this issue to support_at_ranorex.com!
If someone else experiences a similar problem with Ranorex Spy, please contact support_at_ranorex.com and if possible provide a sample application that we can reproduce the crash with!

Regards,
Alex
Ranorex Support Team

cancerion
Posts: 30
Joined: Tue Jun 16, 2009 6:15 pm

Re: STA threading

Post by cancerion » Tue Aug 11, 2009 11:06 am

Hi,

I am using Ranorex 2.1.2 version.
I am also getting same warning
“The apartment state of the current thread is not set to STA. Please make sure that all threads accessing Ranorex methods have their apartment state set to STA.”
in my Ranorex logs. But I am able to execute one test case now. But if I need to executes 200+ test cases in future.
What will be the impact of this issue?

Thanks

atom
Posts: 357
Joined: Sun Dec 07, 2008 11:14 pm
Location: Dublin, Ireland

Re: STA threading

Post by atom » Tue Aug 11, 2009 11:37 am

Depends what your other thread is doing... does it use any Ranorex methods?

User avatar
Support Team
Site Admin
Site Admin
Posts: 12145
Joined: Fri Jul 07, 2006 4:30 pm
Location: Houston, Texas, USA
Contact:

Re: STA threading

Post by Support Team » Tue Aug 11, 2009 12:11 pm

All threads using the Ranorex framework need to have a Single Threaded Apartment (STA) state. For new threads started in your application you need to call the Thread.SetApartmentState method, for the main thread of your automating process you have to apply the STAThreadAttribute to the Main method of your .NET application. If you do not set the apartment state to STA, web testing won't work at all and some attributes of other technologies (MSAA, WPF) won't be accessible.

Ranorex only checks the apartment state of the thread that initializes the Ranorex framework. So, you will get this warning only if the thread first accessing Ranorex classes does not have the STA apartment state.

Regards,
Alex
Ranorex Support Team

markvanraalte
Posts: 13
Joined: Thu Apr 15, 2010 4:34 pm

Re: STA threading

Post by markvanraalte » Wed Apr 21, 2010 11:06 am

Hi
I seem to be having the same problem.
I dumbed down my application to a bare bones program (code below). I have a simple windows form with a single text box and a button.

I have a separate thread that I start which executes in a loop looking for a particular windows form (alert). When it finds the form it reads info from it and sends the info back to controls on my application form.
I am using the background worker method to update my controls via the ProgressChanged as recommended by microsoft.
I keep getting the warning:
"
The apartment state of the current thread is not set to STA. Please make sure that all threads accessing Ranorex methods have their apartment state set to STA.
"
Here is my code in the form (it has a text box called 'txtScanCount' and a button called 'BtnStartScan'). Appreciate any help:

Regards,
Mark


// Listing for MainForm.cs
using System;
using System.Collections.Generic;
using System.Drawing;
using WinForms = System.Windows.Forms;
using System.ComponentModel;

using Ranorex;

namespace MyProj
{
/// <summary>
/// Description of MainForm.
/// </summary>
public partial class MainForm : System.Windows.Forms.Form
{
static System.ComponentModel.BackgroundWorker bw;

public MainForm()
{
//
// The InitializeComponent() call is required for Windows Forms designer support.
//
InitializeComponent();

}

//[STAThread]
void BtnStartScanClick(object sender, EventArgs e)
{
bw = new BackgroundWorker();
bw.WorkerReportsProgress = true;

bw.DoWork += bw_DoWork;
bw.ProgressChanged += bw_ProgressChanged;
bw.RunWorkerAsync (); // Start Scan();
}

//[STAThread]
void bw_ProgressChanged (object sender, ProgressChangedEventArgs e)
{
txtScanCount.Text = e.ProgressPercentage.ToString();
System.Threading.Thread.Sleep(50);

if (e.UserState!=null)
{
//Various operations on the userstate object
}
}


[STAThread]
void bw_DoWork(object sender, DoWorkEventArgs e) // Scan for alerts
{
int scanCount=0;
while (true)
{
// Send scanCount back to main form
bw.ReportProgress (scanCount); // Send scan count to form
try
{
Ranorex.Form frmAlert=Host.Local.FindSingle("/form[@title='Alert activated']",1000);
Report.Info("Scan(); Alert Window Detected." );
// Here we get some info from the Alert window and close it
string formInfo="";
bw.ReportProgress (scanCount, formInfo);
}
catch (Ranorex.ElementNotFoundException e1)
{}// Continue to next scan if form not found

if (scanCount==10) // break out of loop after 10 scans
break;
scanCount++;
}

} //End function doWork


}
}

markvanraalte
Posts: 13
Joined: Thu Apr 15, 2010 4:34 pm

Re: STA threading

Post by markvanraalte » Wed Apr 21, 2010 6:25 pm

Hi,

I seem to have resolved my STA Threading problem by relocating the Ranorex "FindSingle" function into the ProgressChanged method. In other words, I've put the Form search function into the GUI thread instead of the background worker thread.

It seems as if we cant have the GUI interactive functions within the background worker.
My background worker method now simply has a sleep for 3 seconds, and then it sends a message via the ReportProgress event to the ProgressChanged method (on the GUI thread) which calls the FindSingle function.

While the background working is sleeping, I generally have access to my GUI window. It only locks for the short moment of time that the process is running FindSingle. The behaviour is pretty much as I want.

Interested to know if there are any opinions on this solution.

My CSharp code is given below.

Regards,
Mark

// CSharp Listing
using System;
using System.Collections.Generic;
using System.Drawing;
using WinForms = System.Windows.Forms;
using System.ComponentModel;

using Ranorex;

namespace MyProj
{
/// <summary>
/// Description of MainForm.
/// </summary>
public partial class MainForm : System.Windows.Forms.Form
{
static System.ComponentModel.BackgroundWorker bw;

public MainForm()
{
//
// The InitializeComponent() call is required for Windows Forms designer support.
//
InitializeComponent();

}

void BtnStartScanClick(object sender, EventArgs e)
{
bw = new BackgroundWorker();
bw.WorkerReportsProgress = true;

bw.DoWork += bw_DoWork;
bw.ProgressChanged += bw_ProgressChanged;
bw.RunWorkerAsync (); // Start Scan();
}

void bw_ProgressChanged (object sender, ProgressChangedEventArgs e)
{
txtScanCount.Text = e.ProgressPercentage.ToString();

try
{
Report.Info("Scan(); Searching for Alert Window: " + e.ProgressPercentage.ToString() );
Ranorex.Form frmAlert=Host.Local.FindSingle("/form[@title='Alert activated']");
// Here we get some info from the Alert window and close it
}
catch (Ranorex.ElementNotFoundException e1)
{}// Continue to next scan if form not found

if (e.UserState!=null)
{
//Various operations on the userstate object
}
}


void bw_DoWork(object sender, DoWorkEventArgs e) // Scan for alerts
{
int scanCount=1;
while (true)
{
// Send scanCount back to main form
bw.ReportProgress (scanCount); // Send scan count to form
System.Threading.Thread.Sleep(3000);

if (scanCount==2) // break out of loop after 10 scans
break;
scanCount++;
}

} //End function doWork


}
}

User avatar
Support Team
Site Admin
Site Admin
Posts: 12145
Joined: Fri Jul 07, 2006 4:30 pm
Location: Houston, Texas, USA
Contact:

Re: STA threading

Post by Support Team » Thu Apr 22, 2010 9:00 am

markvanraalte wrote:In other words, I've put the Form search function into the GUI thread instead of the background worker thread.
GUI threads always have a Single Threaded Apartment (STA) state (Windows Forms require STA threads). It looks like the BackgroundWorker thread is not STA, but all the event handlers are invoked on the main GUI thread. If you're doing the actual work on the ProgressChanged event, you could even use a simple System.Windows.Forms.Timer component instead.

I don't think you can setup the BackgroundWorker thread to use STA model, since the BackgroundWorker uses the .NET ThreadPool. You could use a simple Thread instead of the BackgroundWorker and set the apartment state of that thread to STA. Note, though, that whenever you try to access the GUI from that newly created thread you need to invoke the call on the GUI thread, e.g. by invoking Control.Invoke on the main thread. See following websites for more info:
http://www.albahari.com/threading/part3 ... nd_Windows
http://msdn.microsoft.com/en-us/library/zyzhdc6b.aspx

Regards,
Alex
Ranorex Support Team

markvanraalte
Posts: 13
Joined: Thu Apr 15, 2010 4:34 pm

Re: STA threading

Post by markvanraalte » Fri Apr 23, 2010 2:15 pm

Thanks Alex

This is really helpful. Now I understand why I cant use the background worker with the STA model.
Also, as you point out I only need a simple timer for my purpose, so I think I'll re write my module using a timer.

Regards,
Mark