UI freezes

  • Thread starter Thread starter Paul
  • Start date Start date
P

Paul

Hi Guys,
I have an application which uses COM object to connect to a "pick"
database.
With this object I can run some select statemnts, however when the
select command is send to the server, my UI freezes and waits for the
connection to return result.
I tried to run the command in separate thread but with no improvement.
Any suggestions are greatly welcomed.
Thanks.
 
Hi Paul,

If you run commands in separate thread it shouldn't freeze the UI.
Can you show us a snippet of the code?
 
Make sure your separate thread is initialized to run in an STA, if you
don't, your COM object will still run on the UI (STA)thread.
Also note that you shouldn't directly update the UI elements from this
thread, you have to call Control.Invoke or Control.BeginInvoke.

Willy.
 
Here is a part of the code. I included only main parts which deal with
this issue. I hope it will give you a picture what I'm trying to do.
The part which takes long time is "m_Tcl.brExecute(oMs,oMs);"

Question for Willy:
You mentioned to run the thread in an STA. Could you please send me
some sample of this?
Thanks
Paul

namespace Pick_Query
{
#region Public Delegates

// delegates used to call MainForm functions from worker thread
public delegate void DelegateAddString(String s);

#endregion
/// <summary>
/// Summary description for MainForm.
/// </summary>

public class MainForm : System.Windows.Forms.Form
{
public MainForm()
{
InitializeComponent();

// initialize delegates
m_DelegateAddString = new DelegateAddString(this.AddLineToOutput);
}

[STAThread]
static void Main()
{
Application.Run(new MainForm());
}

private void button1_Click(object sender, System.EventArgs e)
{

Work work = new Work(this);
ThreadStart threadDelegate = new ThreadStart(work.QueryTest);
Thread newThread = new Thread(threadDelegate);
newThread.Name = "test thread...";
newThread.Start();
}
}

public class Work
{
MainForm mainForm;
public Work(MainForm mform)
{
mainForm = mform;
}
public void QueryTest()
{
string msg;
object oMs = System.Reflection.Missing.Value;
D3CLODBC.clsD3Environment m_Env = null;
D3CLODBC.clsD3Connection m_Con = null;
D3CLODBC.clsD3TclCommand m_Tcl;

//initilize the connection
m_Env = new D3CLODBC.clsD3EnvironmentClass();
m_Con = m_Env.brOpenConnection("ODBC","members_test");
msg = "Connected...";

//send message to the MainForm
mainForm.Invoke(mainForm.m_DelegateAddString,new object[]{msg});

//command to be executed on the D3 server
string cmd = "pq_sort_tab solicitor a1 a2 a3 a4 a5";


m_Tcl = m_Con.brOpenTclCommand(cmd);

// this is the part which takes long time
m_Tcl.brExecute(oMs,oMs); //executing the command

//returning string of stuff
msg = m_Tcl.brCapturing.get_brCString();
mainForm.Invoke(mainForm.m_DelegateAddString,new object[]{msg});
}

}

}
 
Paul said:
Here is a part of the code. I included only main parts which deal with
this issue. I hope it will give you a picture what I'm trying to do.
The part which takes long time is "m_Tcl.brExecute(oMs,oMs);"

Question for Willy:
You mentioned to run the thread in an STA. Could you please send me
some sample of this?
Thanks
Paul

namespace Pick_Query
{
#region Public Delegates

// delegates used to call MainForm functions from worker thread
public delegate void DelegateAddString(String s);

#endregion
/// <summary>
/// Summary description for MainForm.
/// </summary>

public class MainForm : System.Windows.Forms.Form
{
public MainForm()
{
InitializeComponent();

// initialize delegates
m_DelegateAddString = new DelegateAddString(this.AddLineToOutput);
}

[STAThread]
static void Main()
{
Application.Run(new MainForm());
}

private void button1_Click(object sender, System.EventArgs e)
{

Work work = new Work(this);
ThreadStart threadDelegate = new ThreadStart(work.QueryTest);
Thread newThread = new Thread(threadDelegate);
newThread.Name = "test thread...";
newThread.Start();
}
}

public class Work
{
MainForm mainForm;
public Work(MainForm mform)
{
mainForm = mform;
}
public void QueryTest()
{
string msg;
object oMs = System.Reflection.Missing.Value;
D3CLODBC.clsD3Environment m_Env = null;
D3CLODBC.clsD3Connection m_Con = null;
D3CLODBC.clsD3TclCommand m_Tcl;

//initilize the connection
m_Env = new D3CLODBC.clsD3EnvironmentClass();
m_Con = m_Env.brOpenConnection("ODBC","members_test");
msg = "Connected...";

//send message to the MainForm
mainForm.Invoke(mainForm.m_DelegateAddString,new object[]{msg});

//command to be executed on the D3 server
string cmd = "pq_sort_tab solicitor a1 a2 a3 a4 a5";


m_Tcl = m_Con.brOpenTclCommand(cmd);

// this is the part which takes long time
m_Tcl.brExecute(oMs,oMs); //executing the command

//returning string of stuff
msg = m_Tcl.brCapturing.get_brCString();
mainForm.Invoke(mainForm.m_DelegateAddString,new object[]{msg});
}

}

}

No sample needed, just set the ApartmentState property to STA before
starting the thread.

....
newThread.ApartmentState = ApartmentState.STA;
newThread.Start();
.....

As a result you'll have two threads running - the UI and the secondary
thread - each in their own apartment. The COM object will run in the
secondary thread, so no marshalling is required when calling it's methods
from the managed code.

Willy.
 
Willy,
thanks for the reply. I tried that and the UI is still freezing and waiting
for the call to execute the command to finish, after that it becomes responsive.

I'm out of ideas and open to all sugestions.
Thanks again,
Paul
 
Paul,
Could you please chack the COM objects "threadingmodel" attribute in the
registry (or using oleview).

Willy.
 
This is something I was afraid of, looks like you have a real problem now.
A COM object that is marked "None" for it's threadingmodel, is a bad thing
especially in the multithreaded world of .NET and Windows Forms.
The object author indicated by this (maybe not intentional) that this
component was not threading aware.
Can't you contact the vendor and ask for something more .NET/COM friendly.

Willy.
 
Willy Denoyette said:
This is something I was afraid of, looks like you have a real problem now.
A COM object that is marked "None" for it's threadingmodel, is a bad thing
especially in the multithreaded world of .NET and Windows Forms.
The object author indicated by this (maybe not intentional) that this
component was not threading aware.
Can't you contact the vendor and ask for something more .NET/COM friendly.

Willy.

Thanks Willy,
unfortunatelly I can't. I was thinking maybe I should run a separate
program(exe) for this which would run in the background and it
wouldn't matter if it hanged for
while. Is there an easy way how to pass stuff between two independent
programs?

Thanks again,
Peter
 
Hi Paul,

"> Thanks Willy,
unfortunatelly I can't. I was thinking maybe I should run a separate
program(exe) for this which would run in the background and it
wouldn't matter if it hanged for
while. Is there an easy way how to pass stuff between two independent
programs?

Take a look at remoting.
 
Back
Top