Delphi中多线程用Synchronize实现VCL数据同步显示

  VCL实现同步方法就是调用线程类的Synchronize的过程,此过程需要一个无参数的procedure,故在此procedure中无法传递参数值,但可以通过类的成员来实现。在类的Execute中只须调用Synchronize就可以了。

   如果在线程中对VCL赋值操作,在连续执行多次以后,会报“Canvas  does not allow drawing”错误,这个错误可以由上述方法修复,把赋值操作让窗体主线程来完成。

  关键在于对Synchronize参数的定义。定义一个无参数的procedure通过它来访问类的成员变量szName和nIndex。在类的重载Execute中调用Synchronize。

  例证代码:

   1 

 2  procedure  TRunningWatcher.Execute;
 3  begin
 4       { do some thing here }
 5      FreeOnTerminate : =  True;
 6       while  ( not  Terminated)  and  ( not  Application.Terminated)  do
 7       begin
 8         QueryPerformanceFrequency(CounterFrequency);
 9         QueryPerformanceCounter(EndCounter);
10         Synchronize(WatchAction);  { 必须让主线程来运行,否则会报"Canvas  does not allow drawing"错误 }
11         Sleep( 500 );
12          if  ThreadCount  =   0   then   { 如果线程全部退出,需要做最后一次统计 }
13          begin
14           Synchronize(WatchAction);
15           Self.Suspend;
16          end ;
17       end ;
18  end ;
19 
20  { 监视器显示统计信息 }
21  procedure  TRunningWatcher.WatchAction;
22  var
23    iSetCount:Integer;
24    dDiffTime,dPerSecond:Extended;
25  begin
26       iSetCount  : =  ISetValueCount;
27       dDiffTime : =   0 ;
28       dPerSecond : =   0 ;
29        if   not  LessThan(EndCounter, BeginCounter)  then
30        begin
31          dDiffTime : =  (EndCounter - BeginCounter) / CounterFrequency * 1000.0 ;
32          dPerSecond : =  dDiffTime / dDiffTime * 1000 ;
33        end ;
34       Self.mThreadCount.Caption      : =  IntToStr(list.Count);
35       Self.mThreadRun.Caption        : =  IntToStr(ThreadCount);
36       Self.mThreadTerminate.Caption  : =  IntToStr(list.Count - ThreadCount);
37       Self.mTotalCostTime.Caption    : =  FormatFloat( ' 0.00 ' , CalSumValueE(CallServerTimeArr,  0 , iSetCount - 1 ));
38       Self.mCallTimes.Caption        : =  IntToStr(iSetCount);
39       Self.mAvgCostTime.Caption      : =  FormatFloat( ' 0.00 ' , CalAvgValueE(CallServerTimeArr,  0 , iSetCount - 1 ));
40       Self.mMaxCostTime.Caption      : =  FormatFloat( ' 0.00 ' , CalcMaxValueE(CallServerTimeArr,  0 , iSetCount - 1 ));
41       Self.mMinCostTime.Caption      : =  FormatFloat( ' 0.00 ' , CalcMinValueE(CallServerTimeArr,  0 , iSetCount - 1 ));
42       Self.mRunTime.Caption          : =  FormatFloat( ' 0.00 ' , dDiffTime);
43       Self.mSynCallBack.Caption      : =  FormatFloat( ' 0.00 ' , dPerSecond);
44  end ;

 

 程序说明:我这里定义了一些Tlabel的成员变量,根据构造函数来初始化成界面上的对应控件,在这里等同于界面上的label,在Execute函数中不停调用WatchAction过程,起先我的写法如下:

1         QueryPerformanceFrequency(CounterFrequency);
2         QueryPerformanceCounter(EndCounter);
3         WatchAction;  { 必须让主线程来运行,否则会报"Canvas  does not allow drawing"错误 }
4         Sleep( 500 );
5          if  ThreadCount  =   0   then   { 如果线程全部退出,需要做最后一次统计 }
6          begin
7           WatchAction;
8           Self.Suspend;
9          end ;

 

 在连续执行到9k次以上时,报“Canvas  does not allow drawing”错误。修改后解决问题:

 1        QueryPerformanceFrequency(CounterFrequency);

2         QueryPerformanceCounter(EndCounter);
3         Synchronize(WatchAction);  { 必须让主线程来运行,否则会报"Canvas  does not allow drawing"错误 }
4         Sleep( 500 );
5          if  ThreadCount  =   0   then   { 如果线程全部退出,需要做最后一次统计 }
6          begin
7           Synchronize(WatchAction);
8           Self.Suspend;
9          end ;

 

你可能感兴趣的:(Delphi)