新书推介:《语义网技术体系》
作者:瞿裕忠,胡伟,程龚
   XML论坛     W3CHINA.ORG讨论区     计算机科学论坛     SOAChina论坛     Blog     开放翻译计划     新浪微博  
 
  • 首页
  • 登录
  • 注册
  • 软件下载
  • 资料下载
  • 核心成员
  • 帮助
  •   Add to Google

    >> 本版讨论.NET,C#,ASP,VB技术
    [返回] 中文XML论坛 - 专业的XML技术讨论区计算机技术与应用『 Dot NET,C#,ASP,VB 』 → 解决线程访问控件时产生的 CrossThread 方法 查看新帖用户列表

      发表一个新主题  发表一个新投票  回复主题  (订阅本版) 您是本帖的第 9615 个阅读者浏览上一篇主题  刷新本主题   树形显示贴子 浏览下一篇主题
     * 贴子主题: 解决线程访问控件时产生的 CrossThread 方法 举报  打印  推荐  IE收藏夹 
       本主题类别:     
     卷积内核 帅哥哟,离线,有人找我吗?
      
      
      威望:8
      头衔:总统
      等级:博士二年级(版主)
      文章:3942
      积分:27590
      门派:XML.ORG.CN
      注册:2004/7/21

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给卷积内核发送一个短消息 把卷积内核加入好友 查看卷积内核的个人资料 搜索卷积内核在『 Dot NET,C#,ASP,VB 』的所有贴子 访问卷积内核的主页 引用回复这个贴子 回复这个贴子 查看卷积内核的博客楼主
    发贴心情 解决线程访问控件时产生的 CrossThread 方法


    Windows Forms 控件通常不是thread-safe(直接或间接继承于System.Windows.Forms.Control),因此.NET Framework为防止multithread下对控件的存取可能导致控件状态的不一致,在调试时,CLR-Debugger会抛出一个InvalidOperationException以‘建议‘程序员程序可能存在的风险。
    问题的关键在于,动机是什么?和由此而来的编程模型的调整。
    1. Example首先,看一个代码实例。该例要完成的工作是由一个Button的Click触发,启动一个Thread(Manual Thread),该Thread的目的是完成设置TextBox的Text’s Property。
    1.1 Unsafe access to control Code 1.1
    using System;
    using System.Configuration;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Text;
    using System.Windows.Forms;
    using System.Threading;
    using System.IO;
    namespace WindowsApplication1 {
        public partial class Form1 : Form {
            public Form1() {
                InitializeComponent();
            }
             private void unsafeSetTextButton_Click(object sender, EventArgs e) {
                Thread setTextThread = new Thread(new ThreadStart(doWork));
                setTextThread.Start();
            }
             private void doWork() {
                string fileName = ".\\test-src.txt";
                if (!File.Exists(fileName)) {
                    MessageBox.Show(string.Format("{0} doesn't exist!", fileName),
                        "FileNoFoundException");
                    return;
                }
                 string text = null;
                using (StreamReader reader = new StreamReader(fileName, Encoding.Default)) {
                    text = reader.ReadToEnd();
                }
                 this.textBox1.Text = text;
            }
        }
    }

    在调试时,CLR-Debugger会在以上代码中粗体处将会弹出 提示说,当前存取控件的thread非创建控件的thread(Main Thread)。
      1.2 What’s mean?当然,你也可以忽略InvalidOperationException,在非调试的状态下,该异常并不会被抛出,CLR-Debugger监测对Handle的可能存在的不一致地存取,而期望达到更稳健(robust)的代码,这也就是Cross-thread operation not valid后的真正动机。
    但是,放在面前的选择有二:第一,在某些情况下,我们并不需要这种善意的‘建议‘,而这种建议将在调试时带来了不必要的麻烦;第二,顺应善意的‘建议‘,这也意味着我们必须调整已往行之有效且得心应手的编程模型(成本之一),而这种调整额外还会带来side-effect,而这种side-effect目前,我并不知道有什么简洁优雅的解决之道予以消除(成本之二)。
    2. The first choice : CheckForIllegalCrossThreadCalls
    忽略Cross-thread InvalidOperationException建议,前提假设是我们不需要类似的建议,同时也不想给自己的调试带来过多的麻烦。
    关闭CheckForIllegalCrossThreadCalls,这是Control class上的一个static property,默认值为flase,目的在于开关是否对Handle的可能存在的不一致存取的监测;且该项设置是具有Application scope的。
    如果,只需要在某些Form中消除Cross-thread InvalidOperationException建议,可以在Form的.ctor中,InitializeComponent语句后将CheckForIllegalCrossThreadCalls设置为false 。
    Code 2. - 1
    public Form1() {
        InitializeComponent();
         Control.CheckForIllegalCrossThreadCalls = false;
    }


       收藏   分享  
    顶(0)
      




    ----------------------------------------------
    事业是国家的,荣誉是单位的,成绩是领导的,工资是老婆的,财产是孩子的,错误是自己的。

    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2011/10/20 9:07:00
     
     卷积内核 帅哥哟,离线,有人找我吗?
      
      
      威望:8
      头衔:总统
      等级:博士二年级(版主)
      文章:3942
      积分:27590
      门派:XML.ORG.CN
      注册:2004/7/21

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给卷积内核发送一个短消息 把卷积内核加入好友 查看卷积内核的个人资料 搜索卷积内核在『 Dot NET,C#,ASP,VB 』的所有贴子 访问卷积内核的主页 引用回复这个贴子 回复这个贴子 查看卷积内核的博客2
    发贴心情 
    how to access a control from another thread which didn't create this control.

    I faced this issue more than 1 time, I decided to collect info about it and made some changes on the code to simplify this problem to you cause it's really annoying and confusing to work with threading stuff. Here is a small code solves this problem FOREVER and in ANY case.

    Error:

    Cross thread operation not valid: Control "XXXXXXXXXX" accessed from a thread other than the thread it was created.

    Solution:

    1- Create your thread:


    Private Strt As System.Threading.Thread   


    2- Start your thread wherever you want:


      Strt = New System.Threading.Thread(AddressOf MyThread1)
      Strt.Start()


    3- Add the thread sub (MyThread1) and put whatever you want and remember that the lines which access a control from this thread will be separated to into another sub (the Delegate sub)


      Sub MyThread1
           ' Working code
           ' Working code
           ' Working code
           ' Working code
           ' Working code
           ' Working code

           AccessControl()

    End Sub


    From the previous code you will notice 2 things:
    1st: AccessControl the sub which will be delegated.
    2nd: ' Working code - which doesn't need a delegate to get it work. In other mean, it doesn't show up the error message you receive.

    4- and finally, add the delegated sub:


    Private Sub AccessControl()
            If Me.InvokeRequired Then
                Me.Invoke(New MethodInvoker(AddressOf AccessControl))
            Else
        ' Code wasn't working in the threading sub
        ' Code wasn't working in the threading sub
        ' Code wasn't working in the threading sub
        ' Code wasn't working in the threading sub
        ' Code wasn't working in the threading sub
                Button2.Visible = True
                Button3.Visible = True
                Opacity = 1
                ShowInTaskbar = True
            End If
        End Sub


    From the previous code you will notice that all the codes which wasn't working in the threading sub will be added after "Else" line.
    examples for some codes which needs to be delegated:

    ----------------------------------------------
    事业是国家的,荣誉是单位的,成绩是领导的,工资是老婆的,财产是孩子的,错误是自己的。

    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2011/10/20 9:08:00
     
     卷积内核 帅哥哟,离线,有人找我吗?
      
      
      威望:8
      头衔:总统
      等级:博士二年级(版主)
      文章:3942
      积分:27590
      门派:XML.ORG.CN
      注册:2004/7/21

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给卷积内核发送一个短消息 把卷积内核加入好友 查看卷积内核的个人资料 搜索卷积内核在『 Dot NET,C#,ASP,VB 』的所有贴子 访问卷积内核的主页 引用回复这个贴子 回复这个贴子 查看卷积内核的博客3
    发贴心情 
    This error usually shows when Threading operation or Timers are used. UI Controls are naturally belongs to one thread. So if you have another thread to use then use the following simple steps to avoid Cross-Threading

    1- Create your thread:
    private Thread _thread = null;
    private delegate void CrossThreading();

    2- Start your thread wherever you want:
    _thread = new Thread(MyThread1);
    _thread.Start();


    3- Add the thread sub (MyThread1) and put whatever you want and remember that the lines which access a control from this thread will be separated to into another sub (the Delegate sub)

    private void MyThread1()
    {
        MyController w = new MyController();
        this.MyProperty = w.GetResponse(_oLex.LexName);
                
        PoppingUp();
    }


    From the previous code you will notice 2 things:
    1st: PoppingUp() the sub which will be delegated.
    2nd: ' Working code - which doesn't need a delegate to get it work. In other mean, it doesn't show up the error message you receive.

    4- and finally, add the delegated sub:

    private void PoppingUp()
    {
               if (this.InvokeRequired)
               {
                       this.Invoke(new CrossThreading(PoppingUp));
    // Call back on UI thread.            }
               else
               {
                   // WORKING CODE
                   // back to UI thread so change UI controls here

                   lblMyLabelControl.Text = this.MyProperty;
               }
    }

    Now from the previous code you will notice that all the codes which wasn't working in the threading sub will be added after "Else" line.
    examples for some codes which needs to be delegated:
    ddlLocation.Items.Add(...)

    ----------------------------------------------
    事业是国家的,荣誉是单位的,成绩是领导的,工资是老婆的,财产是孩子的,错误是自己的。

    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2011/10/20 9:10:00
     
     GoogleAdSense
      
      
      等级:大一新生
      文章:1
      积分:50
      门派:无门无派
      院校:未填写
      注册:2007-01-01
    给Google AdSense发送一个短消息 把Google AdSense加入好友 查看Google AdSense的个人资料 搜索Google AdSense在『 Dot NET,C#,ASP,VB 』的所有贴子 访问Google AdSense的主页 引用回复这个贴子 回复这个贴子 查看Google AdSense的博客广告
    2024/5/16 4:03:58

    本主题贴数3,分页: [1]

    管理选项修改tag | 锁定 | 解锁 | 提升 | 删除 | 移动 | 固顶 | 总固顶 | 奖励 | 惩罚 | 发布公告
    W3C Contributing Supporter! W 3 C h i n a ( since 2003 ) 旗 下 站 点
    苏ICP备05006046号《全国人大常委会关于维护互联网安全的决定》《计算机信息网络国际联网安全保护管理办法》
    78.125ms