我使用异步拷贝的时候,想同时更新主线程创建的progressBar,代码如下:
class fileProgress
{
       private void ReadFileCallback(IAsyncResult asynResult)
        {            try
            {
                lock (fsoutput)
                {
                    fsoutput.EndRead(asynResult);
                }                //把刚刚读入buffer的流写到目标文件中
                if ((m_lOffsetpos + buffer.Length) < fsoutput.Length)
                {
                    fsinput.BeginWrite(buffer, 0, buffer.Length, null, null);
                }
                
                //写最后一块,可能不满一个buffer,退出
                else if(m_lOffsetpos >= fsoutput.Length)
                {
                    fsinput.BeginWrite(buffer, 0, (int)(fsoutput.Length % buffer.Length), null, null);
                    //m_ProductManageSystem.textBoxFileInfo.Text = "文件复制完毕";
                    fsoutput.Close();
                    fsinput.Close();
                    return;
                }                //正常读,每次读一个buffer
                if ((m_lOffsetpos + buffer.Length) < fsoutput.Length)
                {
                    m_lOffsetpos += buffer.Length;
                    Application.DoEvents();
                    if (m_ProductManageSystem.m_pBar.InvokeRequired)
                    {
                        CallUpdateProgressValue cup = new CallUpdateProgressValue(UpdataPrgressValue);
                        this.BeginInvoke(null, null);
                    }
                    ProgressBar pBar = m_ProductManageSystem.m_pBar;
                    if (m_ProductManageSystem.m_pBar.InvokeRequired == true)
                    {                     
                        MethodInvoker m = new MethodInvoker(UpdataPrgressBar);
                        m.BeginInvoke(null, null);
                    }                    fsoutput.BeginRead(buffer, 0, buffer.Length, new AsyncCallback(ReadFileCallback), null);
                }                //读最后一段,可能不足一个buffer
                else if (m_lOffsetpos + buffer.Length >= fsoutput.Length)
                {
                    fsoutput.BeginRead(buffer, 0, (int)(fsoutput.Length - m_lOffsetpos), new AsyncCallback(ReadFileCallback), null);
                    m_lOffsetpos = fsoutput.Length;
                }
            }
            catch (Exception e)
            {
                MessageBox.Show(e.Message);
            }
        }        private void UpdataPrgressValue()
        {
            //读入一个buffer后,更新进度条显示
            m_ProductManageSystem.m_pBar.Value = Convert.ToInt32(m_lOffsetpos * 100 / fsoutput.Length);
        }
 }每次调用的时候都会提示,“线程间调用无效,从不是创建控件“”的线程调用控件“的运行时错误,我在网上搜索过这个问题,比较疑惑,是不是BeginInvoke一定是contrl类才能调用的?我把我的fileProgress类改为继承control类,还会报错,“在创建窗口句柄之前,不能调用invoke或者BeginInvoke",请各位大侠帮帮忙,折磨好几天了,不知道怎么才行

解决方案 »

  1.   

    用委托来调用form上的控件才行,否则会报告不在同一受控线程内的异常.方法是线程里把传随意一个容器控件进去便于调用 control.invoke 方法, 这个方法是线程安全的然后,建一个委托(方法),完成你更新progressbar的动作, control.invoke 就调用这个方法.---
    可能你还没明白, 如果要源码, 网上很多都能搜到,关键字是 "c# 线程 操作 控件"
      

  2.   

    参考
    http://blog.csdn.net/jinjazz/archive/2008/05/06/2397136.aspx
      

  3.   

    VS.Net群-1号:23266021
    VS.Net群-2号:4510861
    VS.Net群-3号:22671516
    VS.Net群-4号:23266396
    VS.Net群-5号:13047396
    VS.Net群-6号C++:57806388
    VS.Net群-7号WinForm:62365220
    VS.Net群-8号敏捷开发:62365516VS.Net技术群欢迎大家加入,发扬团队互助,长期潜水,将被提出!  
    请注明来自:csdn.
      

  4.   


             private void UpdataPrgressValue() 
            { 
                if (this.InvokeRequired)//这里最关键
                {
                   this.Invoke=(new EventHandler(delegate { UpdataPrgressValue() }));
                }
                else
                {
                //读入一个buffer后,更新进度条显示 
                m_ProductManageSystem.m_pBar.Value = Convert.ToInt32(m_lOffsetpos * 100 / fsoutput.Length); 
                 }      
            } 
      

  5.   

    看一看invoke吧,控件的invoke()if(控件.requiredinvoke)
    {
    }
    else{
    m_ProductManageSystem.m_pBar.Value = Convert.ToInt32(m_lOffsetpos * 100 / fsoutput.Length); 
    }
      

  6.   

            private void UpdataPrgressValue() 
            { 
            } 
    在这个方法里面,用你那个窗口的.Invoke或者进度条控件的.Invoke方法,参数是一个delegate,委托一个方法来更新
    进度条,这个方法会用UI线程去更新,就OK了.
      

  7.   

    多谢各位的回复,问题解决了,确实是用Contral的Invoke而不是文件拷贝类的BeginInvoke :)