这是一个OPC客户端程序 我的“连接”按钮的CLICK事件中写了连接OPC服务器的一些代码.以下是核心代码        private void button1_Click(object sender, EventArgs e)
        {
....省略几行些连接服务器和创建组的
                for (int i = 1; i <= pointCount; i++)
                {
                    ClientHandles[i] = i;
                }                for (int i = 1; i <= pointCount; i++)
                {
                    Retstr[i] = _pointID2[i - 1].ToString(); 
                }
                TheOPCitems.AddItems(pointCount, ref arrRetstr, ref arrClientHandles, out arrServerHandles, out arrErrors, null, null);                for (int i = 1; i <= pointCount; i++)
                {
                    oitem[i] = TheOPCitems.GetOPCItem(Convert.ToInt32(arrServerHandles.GetValue(i)));
                    oitem[i].IsActive = true;
                }
         }OPC服务器端点值有变化时就执行一下DataChange事件,第一次连接的时候(也就是点击“连接”按钮的时候),也会自动执行一下DataChange事件。为了提高速度,我在dataChange事件里面设置了一下,让它第一次运行的时候不要执行datachange事件(用变量First)  datachange事件如下 void DataChange(xxx,fff,ddd,zzz...)   
{
 if (First== 1)
{
 return;
}
..
...
...
}以前DataChange事件里面代码少的时候,点击“连接”按钮时很快就能连上,但现在Datachange里面代码多了,点击“连接”按钮的时候(既第一次运行),程序居然硬直了近两分钟。我就纳闷了,既然第一次连接已经return啦 并没有执行下面的代码 速度为啥会慢呢?不明原因(我猜想..是我之前数组定义的太多了,datachange事件里面用到了许许多多在Form1_Load里面从数据库中提出来的数组,所以速度会变慢,虽然没有去执行,但系统会去做一个“提前准备”,方便之后使用...只是猜想 实在想不出别的原因)..
我逐行断点测试过 当执行完button1_Click以后,程序就硬直两分钟,两分钟后调试位置跑到DataChange事件中.既然这种情况很难改变了,那我干脆就做一个进度条算了,启动的时候有进度条在的话客户好歹还是能接受的。但现在问题是进度条放上面了 也会随着程序的硬直而硬直,都一起“假死”掉了。
我的问题是 用多线程或者什么方法,能不能实现这个进度条的功能。我对多线程不咋了解,很害怕多线程也无法解决这个问题。
希望高手能指点下。
感激不尽!! 感激不尽!!!!!
   

解决方案 »

  1.   

    在假死的迭代里面加入Application.DoEvents();
      

  2.   

    假死的迭代指的是什么位置..我逐行调试的 CLICK事件完事之后就硬直 2分钟之后才去调试dataChange事件
    也就是说实现我想的那个功能还是可行的了是么
      

  3.   

    多线程backgroundworker 
    Application.DoEvents()是为了在加载大量数据时能够有一个数据加载的提示,不至于系统出现假死的现象 
    可确保辅助线程激发的任何事件都由该 UI 线程处理
      

  4.   

    backgroundworker是组件么 怎样引用 
      

  5.   

    backgroundworker是组件 默认就在工具箱里面
    其实就是为了让多线程方便使用而弄出来的东西
      

  6.   

    backgroundworker好东西啊 下点源代码回去研究下 希望可以搞定 
      

  7.   

    backgroundworker在工具箱的组件部分里2分钟很长了,你试试用backgroundworker操作一下,但backgroundworker也只是不让界面暂停,不会让你的业务处理速度提高,我猜2分钟的假死是由代码引起的,仔细检查一下,关键位置单步执行,同时看看各个变量的值
      

  8.   

    可以用“同步进度条”,即使界面卡死了,也可以用API来让进度条显示进度。
      

  9.   

    程序里定义了许多的数组 在Form1_Load里面写了许多对数据库操作的东西 在DataChange里面也用了许许多多次Load事件里面取出的数组 因为客户需要把程序写活 所以里面有许多都是重复的 只不过是修改一下参数
      我猜想在CLICK事件完成之后 程序虽然没有执行DATACHANG里面的那些代码 但是已经“检测”了引用过太多次的数组 所以硬直这么长时间就是为了为程序连接成功后快速引用 也许是OPC这个东西本身有些东西吧 不清楚到底咋回事 纯猜想
      

  10.   

    backgroundworker  dowork 事件 指向你的操作
    然后调用 .RunWorkerAsync(); 就可以开始执行 dowork 了这个时候 主线程 还是 空闲着 你可以放个动画片 跟用户互动一下啥的
    最后执行完毕之后 dowork 最后 加个这个语句:
    Invoke((MethodInvoker)(() => "别xxx看了,干活吧"));
      

  11.   

    delegate void HandleInterfaceUpdateDelegate();  //委托,此为重点 
            HandleInterfaceUpdateDelegate interfaceUpdateHandle; 
          Thread td; 
            public formMain() 
            { 
                InitializeComponent(); 
                interfaceUpdateHandle = new HandleInterfaceUpdateDelegate(StartPro); //实例化委托对象 
            } 
    在你进行操作的方法里第一句加上: 
    this.Invoke(interfaceUpdateHandle);//用指定的参数列表执行指定的委托 最后一行加上: 
    td.Abort(); 
    这是相关的方法。 
    private void chang() 
            { 
                ProcessBar obj = new ProcessBar();注:ProcessBar是你放置图片的窗口 
                obj.ShowDialog(); 
            }         
            public void StartPro() 
            { 
                td= new Thread(chang); 
                td.Start(); 
            } http://topic.csdn.net/u/20090710/13/6a4b93fc-dc7c-41c6-89ec-50a12959feb3.html
      

  12.   

    问题暂未解决 可能是我对多线程不太了解..引起硬直的方法应该是datachange吧 我把头部和尾部都加上了没有作用啊.Change事件的委托在Form1_Load里面   TheOPCgroup.DataChange += new DIOPCGroupEvent_DataChangeEventHandler(XXX_DataChange);
      

  13.   

    //---------------
    //在程序中添加progressBar1控件,并且引用using System.Threading/// <summary>
            /// 控件工作委托
            /// </summary>
            delegate void Work();
            /// <summary>
            /// 线程
            /// </summary>
            Thread td;
            /// <summary>
            /// 线程运行方法(完成功能:死循环处理特定控件)
            /// </summary>
            public void RunThread()
            {
                //建立控件委托
                Work OnWork = new Work(this.ProcessBarWork);
                while (true) 
                {
                    //直接委托方法
                    progressBar1.Invoke(OnWork);
                    System.Threading.Thread.Sleep(100);
                }
            }
            /// <summary>
            /// 进度条Value赋值方法
            /// </summary>
            private void ProcessBarWork() 
            {
                if (progressBar1.Value >= 100) 
                {
                    progressBar1.Value = 0;
                }
                ++progressBar1.Value;
            } 
    //在button1_Click添加下面代码---------------
    //td = new Thread(new ThreadStart(this.RunThread));
    //td.Start();
    //---------------//使用完成后使用td.Abort()结束进程
      

  14.   

    最简单的多线程:new Thread(new ThreadStart(method)).Start();private void method();//你所有的开始操作这样就可以和你的主调用线程分离出另一个子线程去执行了。就算这个子线程阻塞中,主调用线程也不会影响。从而避免假死状态(主调用线程的阻塞状态)。