none
在自定义事件触发后,想更新表单中的进度条,结果出现“线程间操作无效”的提示?! RRS feed

  • 问题

  • 一个用WebRequest类写的异步HTTP上传的程序,自定义了一个事件,用于相应上传数据的进度,代码大致如下:

            public delegate void HttpStateChange(object sender, MyHttpEventArgs e);
            public event HttpStateChange OnHttpStateChange;
    
    	//说明:之前的代码调用"BeginWrite"方法,而下面就是回调函数:
            private void WriteCallBack(IAsyncResult asyncResult)
            {
                RequestState requestState = (RequestState)asyncResult.AsyncState;
                try
                {
                    requestState.dataStream.EndWrite(asyncResult);
                    requestState.byteWritten += requestState.byteRead;
                    MyHttpEventArgs e = new MyHttpEventArgs();
                    e.Percent = (int)(100 * requestState.byteWritten / requestState.byteTotal);
                    requestState.byteRead = requestState.fs.Read(requestState.buffer, 0, cc);
    
    		//触发事件
                    OnHttpStateChange(this, e);
    		//其他代码。。。。。。。。。
                }
                catch (Exception ee)
                {
                    MessageBox.Show(ee.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
    
    
    	//在WinForm中的代码:
    	MyHttpTool http = new MyHttpTool();
            http.OnHttpStateChange += new MyHttpTool.HttpStateChange(http_OnHttpStateChange);
    
            void http_OnHttpStateChange(object sender, MyHttpEventArgs e)
            {
                progressBar1.Value = e.Percent;//结果到这里就报“线程间操作无效”
            }
    

    我不是狠明白,我触发事件的时候,不都已经是异步的吗?怎么到了事件处理程序那里还是会报告“线程间操作无效”的错误呢?

    如果我用“WebClient”类的UploadFileAsync方法:

                WebClient web = new WebClient();
                web.UploadFileCompleted += new UploadFileCompletedEventHandler(web_UploadFileCompleted);

    在“web_UploadFileCompleted”回调函数里面我又可以直接对控件进行操作,请问WebClient是如何做到这一点的?


    da jia hao!

    2014年3月19日 16:56

答案

  • WebClient 在异步回调时使用了 SynchronizationContext,关于它的用法你可以参看 MSDN 。

    “异步”同“线程间操作无效”没有直接关系,不是你使用了“异步”,线程间操作就一定有效; 也不是你不使用“异步”,线程间操作就一定无效。

    跨线程操作 UI 组件,你可以简单的使用 BackgroundWoker 组件,也可以使用控件的 Invoke 方式,当然,最后你也可以直接使用 SynchronizationContext。

    2014年3月20日 1:46
  • 另外请参考:

    如何:对 Windows 窗体控件进行线程安全调用

    It's All About the SynchronizationContext


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    2014年3月20日 12:22
    版主

全部回复

  • WebClient 在异步回调时使用了 SynchronizationContext,关于它的用法你可以参看 MSDN 。

    “异步”同“线程间操作无效”没有直接关系,不是你使用了“异步”,线程间操作就一定有效; 也不是你不使用“异步”,线程间操作就一定无效。

    跨线程操作 UI 组件,你可以简单的使用 BackgroundWoker 组件,也可以使用控件的 Invoke 方式,当然,最后你也可以直接使用 SynchronizationContext。

    2014年3月20日 1:46
  • 另外请参考:

    如何:对 Windows 窗体控件进行线程安全调用

    It's All About the SynchronizationContext


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    2014年3月20日 12:22
    版主