Thread safety

Class library usage, coding and language questions.
User avatar
korrektesoftware.de
Posts: 9
Joined: Tue Jan 29, 2019 5:57 pm

Thread safety

Post by korrektesoftware.de » Sun Feb 16, 2020 10:12 pm

Hi,

I have a question for the Ranorex developers: What part of the Ranorex API is threadsafe?

The following examples work reliable in my tests in the positive and negative case and the time savings can be substantial, however the error messages are usually off and refer to the wrong item if I force a failure of one of the xpaths lookup Tasks.

Example 1 "WhenAny"
Let's say, we have either SphereA or SphereB present on page and both have potentially long load times. When either one appears, click on the one that appears and move on, don't wait for the other to time out.

Code: Select all

[...]
var tasks = new List<Task>();
tasks.Add(Task.Run(() => taskA()));
tasks.Add(Task.Run(() => taskB()));
Task t = Task.WhenAny(tasks);
[...]
and

Code: Select all

void taskA() {        	
  if(r.WhenAny_html.SphereAInfo.Exists()) {r.WhenAny_html.SphereA.Click();}
}
void taskB() {
  if(r.WhenAny_html.SphereBInfo.Exists()) {r.WhenAny_html.SphereB.Click();}
}
Example 2 "WhenAll"
Validate a large number of items while considering that life is short and our processors have many cores and threads:

Code: Select all

[...]
var tasks = new List<Task>();
tasks.Add(Task.Run(() => Validate.Exists("/dom[@page='WhenAll.html']/body/input[@id='a1']",timeout)));
tasks.Add(Task.Run(() => Validate.Exists("/dom[@page='WhenAll.html']/body/input[@id='a2']",timeout)));
tasks.Add(Task.Run(() => Validate.Exists("/dom[@page='WhenAll.html']/body/input[@id='a3']",timeout)));
Task t = Task.WhenAny(tasks);
[...]
Thanks in advance for the "official" reply!
Uwe Schmidt

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

Re: Thread safety

Post by Support Team » Mon Feb 17, 2020 10:30 am

Hello Uwe,

Thank you for your post.

In general, the Ranorex API is thread-safe.
"however the error messages are usually off and refer to the wrong item if I force a failure of one of the xpaths lookup Tasks."
Can you explain that in more detail? Which error messages are wrong?

Thank you in advance.

Best,
Robert

User avatar
korrektesoftware.de
Posts: 9
Joined: Tue Jan 29, 2019 5:57 pm

Re: Thread safety

Post by korrektesoftware.de » Mon Feb 17, 2020 12:31 pm

That's good to hear!

Regarding the error messages, the issue could of course also be with my code or my understanding of Threading. I'll get back with some well prepared examples.

ahoisl
Certified Professional
Certified Professional
Posts: 192
Joined: Fri Sep 07, 2007 8:16 am

Re: Thread safety

Post by ahoisl » Mon Feb 17, 2020 12:56 pm

Some things to add regarding concurrency and the Ranorex API:
  • Make sure that all threads are using STA (Single Threaded Apartment) model. This is needed for some technologies
  • Do not spawn too many threads interacting with UI elements at the same time. Even though the Ranorex API is thread-safe and allows multiple threads running in parallel, usually every application can only be access by a single thread at a time. This is because UI technologies usually all run on a single UI thread and all threads trying to get information from the UI must use that thread
  • Do only invoke Mouse and Keyboard actions from 1 thread. Mouse/keyboard actions are not thread-safe, meaning they can influence each other cause clicks/key inputs to be lost
  • Even if you are using multiple threads, all Report calls will go to one report, i.e. the report is written from a single thread and calls will be dispatched to this thread
Regards,
Alex
Ranorex Team

User avatar
korrektesoftware.de
Posts: 9
Joined: Tue Jan 29, 2019 5:57 pm

Re: Thread safety

Post by korrektesoftware.de » Tue Feb 18, 2020 12:41 am

@Robert After further research, everything seems to work fine, including error messages.

(Full disclosure, sometimes I have trouble when hosting my test html files somewhere on C:\. When I put them on a server it works.)

Here is something that doesn't seem to work well though:

Code: Select all

for (int i = 1; i <= 20; i++) {
  tasks.Add(Task.Run(() => Validate.Exists("/dom[@page='WhenAll.html']/body/input["+i.ToString() + "]")));					
}
Here I get 20 lines of report, all refering to a randomly chosen task. I guess the C# compiler optimizes the loop. This is of course beyond the scope of Ranorex and of what I want to deal with in my work.


@ahoisl Thanks for the information. Obviously I stay clear of UI interactions, and it wouldn't occur to me to press 2 buttons in parallel. My goal would be mostly mass validation, and dealing with long loading optional items.

Regarding the STA, according to what I've seen, implementing my Tasks as STA would be quite inconvenient and wouldn't look nearly as clean as my current flow:

Code: Select all

var tasks = new List<Task>();
tasks.Add(...)
Task.WhenAll(tasks)
Do you know of any specific technologies that need STA? Would you mind sharing some of your code?

ahoisl
Certified Professional
Certified Professional
Posts: 192
Joined: Fri Sep 07, 2007 8:16 am

Re: Thread safety

Post by ahoisl » Tue Feb 18, 2020 8:43 am

korrektesoftware.de wrote:
Tue Feb 18, 2020 12:41 am
@ahoisl Thanks for the information. Obviously I stay clear of UI interactions, and it wouldn't occur to me to press 2 buttons in parallel. My goal would be mostly mass validation, and dealing with long loading optional items.
Even for validations, make sure to not spawn too many threads. As I wrote earlier, even getting information from an element is most of the time a non-parallelizable operation, because UIs only allow a single thread to access information and all calls need to be routed to that single thread.
korrektesoftware.de wrote:
Tue Feb 18, 2020 12:41 am
Regarding the STA, according to what I've seen, implementing my Tasks as STA would be quite inconvenient and wouldn't look nearly as clean as my current flow:
True, the TPL does not fully support STA. There's a community project that provides an StaTaskScheduler, but I don't know if that one works correctly.
The technologies needing STA for sure are: MSAA, UIA, SAP, Web with IE. However, as for example MSAA is a basic technology available for almost all UIs on Windows, some of the other technologies may also need STA.

Summed up, in most cases it would be better to use the Ranorex.PopupWatcher that already handles STA correctly. It's maybe not as convenient as the TPL, but it provides a way to wait for a specific repository item or RanoreXPath and then execute some code on the element, e.g. a validation. Every PopupWatcher class will start a separate STA thread performing the work, so don't create too many instances (and make sure to stop them when no longer needed). Instead, you can instruct a single PopupWatcher to watch for multiple repository items/RanoreXPaths.

Regards,
Alex
Ranorex Team

User avatar
korrektesoftware.de
Posts: 9
Joined: Tue Jan 29, 2019 5:57 pm

Re: Thread safety

Post by korrektesoftware.de » Tue Feb 18, 2020 8:33 pm

Interesting, so do you think one could shoehorn the PopupWatcher into a safe threading framework? Of course a PopupWatcher can watch anything, doesn't have to be popups. But how exactly?

Do I start a Task that calls the PopupWatcher, or can I just spawn a bunch of Popupwatchers and will those be "parallel" by default? I'm going to have to try this out :-D

Very interesting!