public delegate void SetListViewCallBack(string type,string str);
public SetListViewCallBack setListViewCallBack = new SetListViewCallBack(SetListView);private void BeginSetListView(string type,string str)
{
   setListViewCallBack .BeginInvoke(type, str, EndSetListView, setListViewCallBack );
}public void SetListView(string type, string str)
{
 ListViewItem lstViewItem = new ListViewItem();
 lstViewItem.SubItems[0].Text = type;
 lstViewItem.SubItems.Add(str);
 lstViewItem.SubItems.Add(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
 lv_users.Items.Add(lstViewItem);
}private void EndSetListView(IAsyncResult ir)
{
     SetListViewCallBack callbacktemp = (SetListViewCallBack)ir.AsyncState;
     callbacktemp.EndInvoke(ir);
}【lv_users.Items.Add(lstViewItem);】
这一句话就错误了,提示“线程间操作无效: 从不是创建控件“lv_users”的线程访问它”
这个异步操作不是可以对控件赋值么,想问下到底怎么写个公共的方法去异步赋值。

解决方案 »

  1.   

     lv_users.Invoke(new Action(()=> lv_users.Items.Add(lstViewItem)));
    或者用同步上下文
    控件中定义
     SynchronizationContext synchronizationContext = SynchronizationContext.Current;
    然后在属性中
              public 属性名{ set{ synchronizationContext.Post();}}
      

  2.   

    没明白啊。
     SynchronizationContext synchronizationContext = SynchronizationContext.Current;
    这句话是放在什么地方啊。
     public 属性名{ set{ synchronizationContext.Post();}}
    这个定义了  怎么使用啊
      

  3.   


              delegate void SetListViewCallBack(string type, string str);        private void BeginSetListView(string type, string str)
              {
                  
              SetListViewCallBack setListViewCallBack = new SetListViewCallBack(SetListView);
                     setListViewCallBack.BeginInvoke(type, str, EndSetListView, setListViewCallBack);
            }
     
            public void SetListView(string type, string str)
            {
                ListViewItem lstViewItem = new ListViewItem();
                lstViewItem.SubItems[0].Text = type;
                lstViewItem.SubItems.Add(str);
                lstViewItem.SubItems.Add(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
                InvokeSetItem(lstViewItem);//修改处
            }
            private void EndSetListView(IAsyncResult ir)
            {
                SetListViewCallBack callbacktemp = (SetListViewCallBack)ir.AsyncState;
                callbacktemp.EndInvoke(ir);
            }
            //以下为新添加
            protected delegate void SetItemHander(ListViewItem item);
            protected void InvokeSetItem(ListViewItem item)
            {
                SetItemHander d = new SetItemHander(SetItem);
                object arg = (object)item;
                this.Invoke(d, arg);
            }
            protected void SetItem(ListViewItem item)
            {
                lv_users.Items.Add(item);
            }
      

  4.   

    用委托访问
    http://www.cnblogs.com/mokey/articles/2095457.html
      

  5.   

    其实跟委托访问实现结果也是差不多的
    //自定义控件
       private SynchronizationContext synchronizationContext = SynchronizationContext.Current;
            public string Labstr {
                set { synchronizationContext.Post(_v => label1.Text = _v.ToString(), value); }
            }
    //使用控件
    //主线程添加控件
                UserControl1 userControl11 = new UserControl1() { Location = new Point(0), Size = new Size(200, 200) };          
                Controls.Add(userControl11);
                //后台线程给主线程控件赋值
                new Thread(() =>
                {
                    while (true)
                    {
                        Thread.Sleep(1000);
                        userControl11.Labstr = DateTime.Now.ToString();
                    }            }) { IsBackground=true }.Start();
      

  6.   

    不同线程之间是不能进行操作,你可以使用委托回调来实现,或者获取UI线程的同步上下文,具体实现代码参考下面博客4.2部分:http://www.cnblogs.com/zhili/archive/2013/05/10/APM.html
    同时下面也有一些示例代码,你也可以参考下面的代码来实现你自己的需求private void btnDownLoad_Click(object sender, EventArgs e)
            {
                rtbState.Text = "Download............";
                btnDownLoad.Enabled = false;
                if (txbUrl.Text == string.Empty)
                {
                    MessageBox.Show("Please input valid download file url");
                    return;
                }            AsyncMethodCaller methodCaller = new AsyncMethodCaller(DownLoadFileSync);
                methodCaller.BeginInvoke(txbUrl.Text.Trim(), GetResult, null);            // 捕捉调用线程的同步上下文派生对象
                sc = SynchronizationContext.Current;
            }        // 同步下载文件的方法
            // 该方法会阻塞主线程,使用户无法对界面进行操作
            // 在文件下载完成之前,用户甚至都不能关闭运行的程序。
            private string DownLoadFileSync(string url)
            {
                // Create an instance of the RequestState 
                RequestState requestState = new RequestState();
                try
                {
                    // Initialize an HttpWebRequest object
                    HttpWebRequest myHttpWebRequest = (HttpWebRequest)WebRequest.Create(url);                // assign HttpWebRequest instance to its request field.
                    requestState.request = myHttpWebRequest;
                    requestState.response = (HttpWebResponse)myHttpWebRequest.GetResponse();
                    requestState.streamResponse = requestState.response.GetResponseStream();
                    int readSize = requestState.streamResponse.Read(requestState.BufferRead, 0, requestState.BufferRead.Length);                while (readSize > 0)
                    {
                        requestState.filestream.Write(requestState.BufferRead, 0, readSize);
                        readSize = requestState.streamResponse.Read(requestState.BufferRead, 0, requestState.BufferRead.Length);
                    }                // 执行该方法的线程是线程池线程,该线程不是与创建richTextBox控件的线程不是一个线程
                    // 如果不把 CheckForIllegalCrossThreadCalls 设置为false,该程序会出现“不能跨线程访问控件”的异常
                    return string.Format("The Length of the File is: {0}", requestState.filestream.Length) + string.Format("\nDownLoad Completely, Download path is: {0}", requestState.savepath);
                }
                catch (Exception e)
                {
                    return string.Format("Exception occurs in DownLoadFileSync method, Error Message is:{0}", e.Message);
                }
                finally
                {
                    requestState.response.Close();
                    requestState.filestream.Close();
                }
            }        // 异步操作完成时执行的方法
            private void GetResult(IAsyncResult result)
            {
                AsyncMethodCaller caller = (AsyncMethodCaller)((AsyncResult)result).AsyncDelegate;
                // 调用EndInvoke去等待异步调用完成并且获得返回值
                // 如果异步调用尚未完成,则 EndInvoke 会一直阻止调用线程,直到异步调用完成
                string returnstring = caller.EndInvoke(result);            // 通过获得GUI线程的同步上下文的派生对象,
                // 然后调用Post方法来使更新GUI操作方法由GUI 线程去执行
                sc.Post(ShowState,returnstring);      
            }        // 显示结果到richTextBox
            // 因为该方法是由GUI线程执行的,所以当然就可以访问窗体控件了
            private void ShowState(object result)
            {
                rtbState.Text = result.ToString();
                btnDownLoad.Enabled = true;
            }
        }
      

  7.   


    这个方法可以实现。但是我这也是异步的啊,就是里面没有去invoke。
    我如果里面有个lable
    直接lbState.Text = “啊啊啊”; 是可以赋值的啊   怎么控件不一样就不能赋值了
      

  8.   

    public void SetListView(string type, string str)
    {
     ListViewItem lstViewItem = new ListViewItem();
     lstViewItem.SubItems[0].Text = type;
     lstViewItem.SubItems.Add(str);
     lstViewItem.SubItems.Add(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
     //lv_users.Items.Add(lstViewItem);
     //修改为
      lbState.Text = “啊啊啊”; 
    }
    就可以了,都是控件。怎么有的可以  有的不可以。
      

  9.   

    跨线程需要空间的RequireedInvoke属性的判断,改写如下:
    lv_users.Invoke(new Action<ListViewItem>(list)=>
    {
      lv_users.Items.Add(list)
    },lstViewItem
    )