1

Somewhere on my main thread i make a new thread which creates an object that is only allowed to be instantiated once through the entire application time.

Further down my main thread i have a function that makes use of this object that is also a global variable by the way.

So i wish to run this function on the same thread that the object was created.

Question is how can i achieve this when it is the Main threads decision when this function should be called?

// global variable private static IWebDriver driver; // Main Thread thread creation Thread thread = new Thread(() => { driver = new ChromeDriver(@"myPath"); }); thread.Start(); // some click event on main thread myFunctionUsingDriverObject(); 

So i need some way to tell the function to run on the same thread as driver was created. Usually you would use the methodInvoker but the IWebDriver does not have such a method. So is there another way i can invoke the function into the thread of driver?

If anyone is wondering why i want to do this. Then it is because the UI is run on the Main Thread and then the function will freeze the UI until completion if it is also run on the main thread.

6
  • Why not create a new thread? Simplest and uglies way is to create a new thread and put a while (true) to check if the driver is still null, then continue with myFunctionUsingDriverObject()? Commented Nov 22, 2017 at 16:38
  • @SoroushFalahati I believe OP wants to implement functionality similar to "UI thread" and Dispatcher.Invoke in WPF where some objects must be only accessed on "UI thread". This is quite common requirement as some objects (particularly Windows UI once) may behave incorrectly when used from thread that is different from one that created them. Commented Nov 22, 2017 at 16:40
  • I think you are looking for bing.com/search?q=c%23+schedule+task+particular+thread like stackoverflow.com/questions/30719366/…. (May be even duplicate) Commented Nov 22, 2017 at 16:42
  • @AlexeiLevenkov, I am not sure. He says that he cant create a new ChromeDriver as it blocks the main thread. Then he wants to run myFunctionUsingDriverObject() with the resulting ChromeDriver from the other thread. Commented Nov 22, 2017 at 16:42
  • @SoroushFalahati yes, exactly what I tried to say - replicate "UI thread" + Invoke functionality with custom thread "My Special Thread" + MySpecialThreadInvoke... Commented Nov 22, 2017 at 16:45

2 Answers 2

2

Add a reference to the WindowsBase.dll and write this code:

 private static IWebDriver driver; private static Dispatcher dispatcher = null; AutoResetEvent waitHandle = new AutoResetEvent(false); var thread = new Thread(() => { dispatcher = Dispatcher.CurrentDispatcher; waitHandle.Set(); Dispatcher.Run(); }); thread.Start(); waitHandle.WaitOne(); // Now you can use dispatcher.Invoke anywhere you want dispatcher.Invoke(() => { driver = new ChromeDriver(@"myPath"); }); // And async for not blocking the UI thread dispatcher.BeginInvoke(new Action(() => { myFunctionUsingDriverObject(); })); // or using await await dispatcher.InvokeAsync(() => { }); // And when you are done, you can shut the thread down dispatcher.InvokeShutdown(); 
Sign up to request clarification or add additional context in comments.

Comments

0

You could use a singleton class or if you wanted to ensure that this could only run once for all applications, a service class that is based on a Mutex. I will show you the former as this seems more applicable as far as I can make out

public interface IDriverService { void StartDriverService(); void StopDriverService(); void PerformDriverAction(); } 

Now an implementation

public class ChromeDriverService : IDriverService { private static ChromeDriverService instance; private readonly Thread _thread; private readonly ConcurrentQueue<Action> _actions = new ConcurrentQueue<Action>(); private volatile bool _running; private ChromeDriverService() { _thread = new Thread(); _thread.Start(); } public static IDriverService Instance() { if (instance == null) instance = new ChromeDriverService(); return instance; } // This will run on the "target" _thread public void StartDriverService() { while (true) { Action action; if (_actions.TryDequeue(out action)) { try { action(); } catch (Exception ex) { // Handle } } else { if (!_running && _actions.IsEmpty) return; } } } public void StopDriverService() { _running = false; // IMPORTANT: Finish the logic here - we have a chance for race conditions. Dequeuing before the // last action runs for example. This is primative, but you will have to take care of this. while (!_actions.IsEmpty) { // Do stuff. } } // Called from some other thread. public void PerformDriverAction(Action action) { if (_running) _actions.Enqueue(action); } } 

This is a primitive example and I have not attempted to run or compile this (I am on my phone).

Note, I am not doing anything with the actual ChromeDriver. This class can be simply edited to work with such an object.

I hope this helps.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.