E
Erakis
Hi,
My application has to start a worker thread and the user may cancel the
process at any time. To do that I'm creating and starting a Thread object. In
this worker thread I update the UI using Control.Invoke(...) I noticed that
UI is not well responding, I mean the stop button click is not always
handled. Here is the minimum code listing to understand my problem.
/ **********************************************************
Main form code
***********************************************************/
public delegate void AddLogEntryDelegate(string entry);
public delegate void ThreadFinishedDelegate();
private void AddLogEntry(string entry)
{
// Append color text to the RichText box
int num = this.m_Txt_Log.TextLength;
// Add new entry
string leftInfo = DateTime.Now.ToString() + " -> ";
int leftInfoLength = leftInfo.Length;
this.m_Txt_Log.AppendText( DateTime.Now.ToString() + " -> " + entry +
Environment.NewLine);
this.m_Txt_Log.Select( num, num + leftInfoLength );
this.m_Txt_Log.SelectionColor = Color.FromArgb( 58, 83, 128 );
this.m_Txt_Log.Select( num + leftInfoLength, this.m_Txt_Log.TextLength -
1 );
this.m_Txt_Log.SelectionColor = Color.FromArgb( 0, 0, 0 );
this.m_Txt_Log.Focus();
}
private void m_Bt_Play_Click(object sender, System.EventArgs e)
{
// Reset events
m_EventStopThread.Reset();
m_EventThreadStopped.Reset();
// Start thread
m_ThreadScript = new Thread( new ThreadStart( this.ScriptThreadFunction
) );
m_ThreadScript.Start();
// Disable command that cannot be activated while in run mode
this.m_Bt_Play.Enabled = false;
this.m_Bt_Stop.Enabled = true;
}
private void m_Bt_Stop_Click(object sender, System.EventArgs e)
{
// Disable stop button
this.m_Bt_Stop.Enabled = false;
// Is thread is active
if ( m_ThreadScript != null && m_ThreadScript.IsAlive )
{
// Set event "Stop"
m_EventStopThread.Set();
// Wait when thread will stop or finish
while (m_ThreadScript.IsAlive)
{
if ( WaitHandle.WaitAll( (new ManualResetEvent[]
{m_EventThreadStopped}), 10, true) )
{
break;
}
// Process all windows messages
Application.DoEvents();
}
}
// Reset button state
this.m_Bt_Play.Enabled = true;
this.m_Bt_Stop.Enabled = false;
}
private void ScriptThreadFunction()
{
new ScriptProcess(m_EventStopThread, m_EventThreadStopped, this).Run();
}
/ **********************************************************
ScriptProcess code
***********************************************************/
public ScriptProcess(ManualResetEvent eventStop, ManualResetEvent
eventStopped, FormPrincipal form)
{
m_EventStop = eventStop;
m_EventStopped = eventStopped;
m_FormPrincipal = form;
}
public void Run()
{
bool bStopThread = false;
int iDelay = 20;
while ( !bStopThread )
{
// Watch for thread stopped event
// and wait (iDelay * 10) millisecons to slow thread
if (iDelay > 0)
{
if ( m_EventStop.WaitOne(10, true) )
{
bStopThread = true;
}
iDelay -= 1;
// Give application time to process it message
// Like the stop button or the exit button of the form
Application.DoEvents();
continue;
}
// Reset delay
iDelay = 20;
// Give application time to process it message
// Like the stop button or the exit button of the form
Application.DoEvents();
/********************************************
// Do script process here (many line cut to make code much easier to
read) !
// Main UI are updated many time by calling this function (Invoke)
// I also tried to use BeginInvoke but I got the same problem about
bad the UI responsivity.
m_FormPrincipal.Invoke(m_FormPrincipal.m_DelegateAddLogEntry, new
object[] {"Doing something..."});
********************************************/
// Give application time to process it message
// Like the stop button or the exit button of the form
Application.DoEvents();
}
// Make synchronous call to main form to inform it that thread finished
m_FormPrincipal.Invoke(m_FormPrincipal.m_ThreadFinishedDelegate, null);
// Thread stopped
m_EventStopped.Set();
}
Is there something wrong with that code ? Usually I'm coding using Visual
C++ and SendMessage and I never get any problem with UI responsivity. I
noticed that puttin alot of Application.DoEvents in the process help the
responsivity but I don't think it is a good solution because that doesn't
work perfectly.
PS : I cannot use anything else then C# .NET 1.1.
Best regards,
Martin
My application has to start a worker thread and the user may cancel the
process at any time. To do that I'm creating and starting a Thread object. In
this worker thread I update the UI using Control.Invoke(...) I noticed that
UI is not well responding, I mean the stop button click is not always
handled. Here is the minimum code listing to understand my problem.
/ **********************************************************
Main form code
***********************************************************/
public delegate void AddLogEntryDelegate(string entry);
public delegate void ThreadFinishedDelegate();
private void AddLogEntry(string entry)
{
// Append color text to the RichText box
int num = this.m_Txt_Log.TextLength;
// Add new entry
string leftInfo = DateTime.Now.ToString() + " -> ";
int leftInfoLength = leftInfo.Length;
this.m_Txt_Log.AppendText( DateTime.Now.ToString() + " -> " + entry +
Environment.NewLine);
this.m_Txt_Log.Select( num, num + leftInfoLength );
this.m_Txt_Log.SelectionColor = Color.FromArgb( 58, 83, 128 );
this.m_Txt_Log.Select( num + leftInfoLength, this.m_Txt_Log.TextLength -
1 );
this.m_Txt_Log.SelectionColor = Color.FromArgb( 0, 0, 0 );
this.m_Txt_Log.Focus();
}
private void m_Bt_Play_Click(object sender, System.EventArgs e)
{
// Reset events
m_EventStopThread.Reset();
m_EventThreadStopped.Reset();
// Start thread
m_ThreadScript = new Thread( new ThreadStart( this.ScriptThreadFunction
) );
m_ThreadScript.Start();
// Disable command that cannot be activated while in run mode
this.m_Bt_Play.Enabled = false;
this.m_Bt_Stop.Enabled = true;
}
private void m_Bt_Stop_Click(object sender, System.EventArgs e)
{
// Disable stop button
this.m_Bt_Stop.Enabled = false;
// Is thread is active
if ( m_ThreadScript != null && m_ThreadScript.IsAlive )
{
// Set event "Stop"
m_EventStopThread.Set();
// Wait when thread will stop or finish
while (m_ThreadScript.IsAlive)
{
if ( WaitHandle.WaitAll( (new ManualResetEvent[]
{m_EventThreadStopped}), 10, true) )
{
break;
}
// Process all windows messages
Application.DoEvents();
}
}
// Reset button state
this.m_Bt_Play.Enabled = true;
this.m_Bt_Stop.Enabled = false;
}
private void ScriptThreadFunction()
{
new ScriptProcess(m_EventStopThread, m_EventThreadStopped, this).Run();
}
/ **********************************************************
ScriptProcess code
***********************************************************/
public ScriptProcess(ManualResetEvent eventStop, ManualResetEvent
eventStopped, FormPrincipal form)
{
m_EventStop = eventStop;
m_EventStopped = eventStopped;
m_FormPrincipal = form;
}
public void Run()
{
bool bStopThread = false;
int iDelay = 20;
while ( !bStopThread )
{
// Watch for thread stopped event
// and wait (iDelay * 10) millisecons to slow thread
if (iDelay > 0)
{
if ( m_EventStop.WaitOne(10, true) )
{
bStopThread = true;
}
iDelay -= 1;
// Give application time to process it message
// Like the stop button or the exit button of the form
Application.DoEvents();
continue;
}
// Reset delay
iDelay = 20;
// Give application time to process it message
// Like the stop button or the exit button of the form
Application.DoEvents();
/********************************************
// Do script process here (many line cut to make code much easier to
read) !
// Main UI are updated many time by calling this function (Invoke)
// I also tried to use BeginInvoke but I got the same problem about
bad the UI responsivity.
m_FormPrincipal.Invoke(m_FormPrincipal.m_DelegateAddLogEntry, new
object[] {"Doing something..."});
********************************************/
// Give application time to process it message
// Like the stop button or the exit button of the form
Application.DoEvents();
}
// Make synchronous call to main form to inform it that thread finished
m_FormPrincipal.Invoke(m_FormPrincipal.m_ThreadFinishedDelegate, null);
// Thread stopped
m_EventStopped.Set();
}
Is there something wrong with that code ? Usually I'm coding using Visual
C++ and SendMessage and I never get any problem with UI responsivity. I
noticed that puttin alot of Application.DoEvents in the process help the
responsivity but I don't think it is a good solution because that doesn't
work perfectly.
PS : I cannot use anything else then C# .NET 1.1.
Best regards,
Martin