2013-07-10
卡住很有可能是因为在窗体的Invoke里进行了大量运算。
一般情况,在线程中就仅仅进行和窗体无关的计算,必要时,使用Invoke进行一些窗体状态的更新,这样完全不会导致卡住冻结。
2010-09-25 18:57更新:根据各位朋友的回复,做了一些更新。
加入了BackgroundWorker和MethodInvoker
有时候我们在窗体的执行方法中,会延迟很久,那样就会造成操作窗体(界面)卡住(冻结)的情况出现,这样的用户体验非常糟糕。
在使用线程操作,则可能会避免这种情况。
因此我做了一个测试。
在这方面的设计,我也是初学者,因此,有不对的地方,请前辈指点迷津。
///
<summary>
/// 执行的主逻辑
/// </summary>
/// <param name="obj"></param>
private void RunMethod( object obj)
{
ThreadTest tt = new ThreadTest();
int curValue = 0 ;
for ( int i = 0 ; i < 20 ; i ++ )
{
curValue = tt.GetRandomNum();
// 不添加5的项,主要为了添加业务复杂性
while (curValue == 5 )
{
Thread.Sleep( 2000 ); // 制造延迟,测试是否会冻结(卡)主窗口
curValue = tt.GetRandomNum();
}
Thread.Sleep( 2000 ); // 制造延迟,测试是否会冻结(卡)主窗口
if ( this .InvokeRequired)
{
this .Invoke( new MethodInvoker( delegate ()
{
this .lsbShow.Items.Add(curValue);
this .lsbShow.SelectedIndex = lsbShow.Items.Count - 1 ;
}));
}
else
{
lsbShow.Items.Add(curValue);
}
}
this .Invoke( new MethodInvoker( delegate ()
{
this .btnRun.Enabled = true ;
this .btnThread.Enabled = true ;
btnBackgroundWorker.Enabled = true ;
this .lsbShow.Items.Add( " Done " );
this .lsbShow.SelectedIndex = lsbShow.Items.Count - 1 ;
}));
}
/// 执行的主逻辑
/// </summary>
/// <param name="obj"></param>
private void RunMethod( object obj)
{
ThreadTest tt = new ThreadTest();
int curValue = 0 ;
for ( int i = 0 ; i < 20 ; i ++ )
{
curValue = tt.GetRandomNum();
// 不添加5的项,主要为了添加业务复杂性
while (curValue == 5 )
{
Thread.Sleep( 2000 ); // 制造延迟,测试是否会冻结(卡)主窗口
curValue = tt.GetRandomNum();
}
Thread.Sleep( 2000 ); // 制造延迟,测试是否会冻结(卡)主窗口
if ( this .InvokeRequired)
{
this .Invoke( new MethodInvoker( delegate ()
{
this .lsbShow.Items.Add(curValue);
this .lsbShow.SelectedIndex = lsbShow.Items.Count - 1 ;
}));
}
else
{
lsbShow.Items.Add(curValue);
}
}
this .Invoke( new MethodInvoker( delegate ()
{
this .btnRun.Enabled = true ;
this .btnThread.Enabled = true ;
btnBackgroundWorker.Enabled = true ;
this .lsbShow.Items.Add( " Done " );
this .lsbShow.SelectedIndex = lsbShow.Items.Count - 1 ;
}));
}
用到的测试类
public
delegate
void
CommonDelegate();
public class ThreadTest
{
public ThreadTest() { }
public int GetRandomNum()
{
Random rd = new Random();
return rd.Next( 1 , 10 );
}
}
public class ThreadTest
{
public ThreadTest() { }
public int GetRandomNum()
{
Random rd = new Random();
return rd.Next( 1 , 10 );
}
}
调用按钮事件
private
void
btnRun_Click(
object
sender, EventArgs e)
{
RunStart();
ThreadPool.QueueUserWorkItem( new WaitCallback(RunMethod));
}
private void btnThread_Click( object sender, EventArgs e)
{
RunStart();
Thread td = new Thread( new ParameterizedThreadStart(RunMethod));
td.Start( "" );
}
private void RunStart()
{
lsbShow.Items.Clear();
btnRun.Enabled = false ;
btnThread.Enabled = false ;
btnBackgroundWorker.Enabled = false ;
}
private void btnBackgroundWorker_Click( object sender, EventArgs e)
{
RunStart();
using (BackgroundWorker bw = new BackgroundWorker())
{
bw.DoWork += new DoWorkEventHandler(bw_DoWork);
bw.RunWorkerAsync();
}
}
void bw_DoWork( object sender, DoWorkEventArgs e)
{
RunMethod( "" );
}
{
RunStart();
ThreadPool.QueueUserWorkItem( new WaitCallback(RunMethod));
}
private void btnThread_Click( object sender, EventArgs e)
{
RunStart();
Thread td = new Thread( new ParameterizedThreadStart(RunMethod));
td.Start( "" );
}
private void RunStart()
{
lsbShow.Items.Clear();
btnRun.Enabled = false ;
btnThread.Enabled = false ;
btnBackgroundWorker.Enabled = false ;
}
private void btnBackgroundWorker_Click( object sender, EventArgs e)
{
RunStart();
using (BackgroundWorker bw = new BackgroundWorker())
{
bw.DoWork += new DoWorkEventHandler(bw_DoWork);
bw.RunWorkerAsync();
}
}
void bw_DoWork( object sender, DoWorkEventArgs e)
{
RunMethod( "" );
}