I have a dedicated class that includes a BackgroundWorker that is responsible for running class-specific actions from a queue - actions which require use of a COM object.
Objects the dedicated class are created during runtime from the UI thread when the application starts up (WPF). When the class' constructor is called, it instantiates a BackgroundWorker that runs asynchronously dequeuing Actions assigned from the UI thread.
However, when these Actions require data resulting from the COM object, I notice that the UI thread is waiting on the BackgroundWorker to finish the Action before reacting to user input.
How can I isolate so that the UI thread is not impacted by the COM's functions that can take up to 10 seconds to complete?
Code:
public class User(){
private BackgroundWorker Worker;
private Queue<Action> ActionQueue;
private COM COMObject; // COM is an interface exposed by the COM referenced in VS project
private bool Registered;
public User(){
this.Registered = true;
this.ActionQueue = new Queue<Action>();
this.Worker = new BackgroundWorker();
this.Worker.DoWork += new DoWorkEventHandler(DoWork);
this.Worker.DoWork += new RunWorkerCompletedEventHandler(WorkerCompleted);
this.Worker.Worker.WorkerSupportsCancellation = true;
this.Worker.Worker.RunWorkerAsync();
this.COMObject = new COM();
}
private DoWork(object sender, DoWorkEventArgs e){
// If there is something to be done (an action) in the queue
if (ActionQueue.Count > 0){
// Dequeue the action from the queue
Action queuedAction = ActionQueue.Dequeue();
// Do the action
queuedAction();
}
}
private void WorkerCompleted(object sender, RunWorkerCompletedEventArgs e){
// While this machine continues to be registered to the app...
if (this.Registered)
{
Worker.RunWorkerAsync();
}
}
public void ConnectToDatabase(){
Action action = delegate {
COMObject.Connect(); // function can take up to 10 seconds to return
}; // end of action delegate
ActionQueue.Enqueue(action);
}
}
Use Code (in UI thread):
User user = new User();
user.ConnectToDatabase();
In my UI, during application startup, there can be up to 10 User
objects created and called to connect. If I comment out the COMObject.Connect();
line in User::ConnectToDatabase and replace with Thread.Sleep(10000)
the UI thread does not wait 10+ seconds. But, as is the code now, I notice that the COMObject.Connect();
line does result in 10+ seconds before any user input in the WPF app is processed again.
How can I isolate so that the functions related to the COM object do not impact the performance of the UI thread?
(Note: there is no interaction with the UI thread from the actions queued with the BackgroundWorker. Only class-specific properties are changed in those actions).