精华内容
下载资源
问答
  • 跨线程访问

    千次阅读 2019-12-31 15:51:20
    创建一个Winfrom程序 ...点击“测试”,创建一个线程,从0循环到10000给文本框赋值,代码如下: public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void btnS...

    创建一个Winfrom程序

    点击“测试”,创建一个线程,从0循环到10000给文本框赋值,代码如下:

    public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }
    
            private void btnStart_Click(object sender, EventArgs e)
            {
                //创建线程
                Thread thread = new Thread(Test);
                //把线程设置为后台线程
                thread.IsBackground = true;
                thread.Start();
            }
    
            private void Test()
            {
                for (int i = 0; i < 10000; i++)
                {
                    this.txtNum.Text = i.ToString();
                }
            }
        }

    运行结果:

    产生错误的原因:txtNum是由主线程创建的,thread线程是另外创建的一个线程,在.NET上执行的是托管代码,C#强制要求这些代码必须是线程安全的,即不允许跨线程访问Windows窗体的控件。

    解决方案:

    1、在窗体的加载事件中,将C#内置控件(Control)类的CheckForIllegalCrossThreadCalls属性设置为false,屏蔽掉C#编译器对跨线程调用的检查。

     private void Form1_Load(object sender, EventArgs e)
     {
         Control.CheckForIllegalCrossThreadCalls = false;
     }

    使用上述的方法虽然可以保证程序正常运行并实现应用的功能,但是在实际的软件开发中,做如此设置是不安全的(不符合.NET的安全规范),在产品软件的开发中,此类情况是不允许的。如果要在遵守.NET安全标准的前提下,实现从一个线程成功地访问另一个线程创建的控件,可以使用C#的方法回调机制。

    2、使用回调函数

    什么叫回调函数呢?比如,你调用了一个函数,那么就叫调用,但是如果你在调用一个函数的时候,还需要把一个函数提供该函数,让这个函数来调用你的函数,那么你提供的这个函数就被称为回调函数(callback),C#的方法回调函数(机制),也是建立在委托基础上的。

    改进后的代码:

     public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }
            //定义回调
            private delegate void setTextValueCallBack(int value);
    
            private void btnStart_Click(object sender, EventArgs e)
            {
                //创建线程
                Thread thread = new Thread(Test);
                //把线程设置为后台线程
                thread.IsBackground = true;
                thread.Start();
            }
            private void Test()
            {
                for (int i = 0; i < 10000; i++)
                {
                    if (txtNum.InvokeRequired)//如果为跨线程访问
                    {
                        //new Action<int>(n=> {this.txtNum.Text = n.ToString();})----创建匿名函数
                        txtNum.Invoke(new Action<int>(n=> {
                            txtNum.Text = n.ToString();
                        }),i);
                        //txtNum.Invoke拥有此控件的基础窗口句柄的线程上执行指定的委托。
                        //也就是说,Invoke()是一个方法,这方法执行的是委托,并且是在一个固定的线程上执行的。
                    }
                }
            }
            private void Form1_Load(object sender, EventArgs e)
            {
                Control.CheckForIllegalCrossThreadCalls = false;
            }
        }

    这样就可以正常运行了,以上就是跨线程访问的方法。

    Demo链接:https://github.com/wangongshen/Wgs.CSDN.Demo2019

    展开全文
  • 跨线程访问winform控件

    2018-04-03 09:14:26
    跨线程访问winform控件;跨线程访问winform控件;跨线程访问winform控件
  • C# 跨线程访问UI线程控件 在C#中,由于使用线程和调用UI的线程属于两个不同的线程,如果在线程中直接设置UI元素的属性,此时就会出现跨线程错误。    下面介绍两种解决方案  第一种:使用控件自带的Invoke或者...
  • 跨线程访问Windows窗体控件,线程带多参数。 跨线程访问Windows窗体控件,线程带多参数。
  • 主要介绍了C#多线程与跨线程访问界面控件的方法,实例分析了C#多线程与跨线程访问空间的技巧,具有一定参考借鉴价值,需要的朋友可以参考下
  • 下面介绍几种跨线程访问的方法: 1、禁止对跨线程访问做检查 (不推荐使用这种方法) 这种方法不检查跨线程访问,允许各个线程操作UI元素,容易出现错误。 public Form2() { InitializeComponent(); //禁止对...
  • 本文实例讲述了C#中WinForm跨线程访问控件的实现方法,分享给大家供大家参考。 具体实现方法如下: 1、跨线程访问控件委托和类的定义 代码如下:using System; using System.Windows.Forms; namespace ahwildlife....
  • 跨线程访问控件实例,解决两个线程之间的控件访问,此方法可以不用委托即可实现。
  • 调用直接调用WriteToButton() 方法即可。 跨线程访问/多线程访问 方法一: public void WriteToButton(string str) { Thread thread = new Thread(() => { ChangeText(str);

    调用直接调用WriteToButton() 方法即可。

    跨线程访问/多线程访问

    方法一:

           public delegate void WriteToBut(string str);
            public void WriteToButton(string str)
            {
                Thread thread = new Thread(() =>
                {
                    ChangeText(str);
                }
                );
                thread.IsBackground = true;
                thread.Start();
            }
            private void ChangeText(string str)
            {
                if (button1.InvokeRequired)//线程外面的想访问它
                {
                    WriteToBut del = new WriteToBut(ChangeText);
                    // this.Invoke(del, str);//同步处理,等待处理完后处理
                    BeginInvoke(del, str);//异步处理
                }
                else
                    button1.Text = str;
            }

    未完待续。。。




    展开全文
  • 第二种方法是禁止编译器对跨线程访问作检查,可以实现访问,但是出不出错不敢保证Control.CheckForIllegalCrossThreadCalls = false; 最近我在做一个项目,遇到了跨线程要去访问页面控件.但是总是提示出错,不能在其它...
  • C#跨线程访问

    2019-05-17 09:59:00
    在C# 的应用程序开发中, 我们经常要把UI线程...第一种办法:禁止编译器对跨线程访问做检查 第二种办法: 使用delegate和invoke来从其他线程中调用控件 第三种办法: 使用delegate和BeginInvoke来从其他线程中控制控...

    在C# 的应用程序开发中, 我们经常要把UI线程和工作线程分开,防止界面停止响应。  同时我们又需要在工作线程中更新UI界面上的控件,

    下面介绍几种常用的方法

     

    阅读目录

    1. 线程间操作无效
    2. 第一种办法:禁止编译器对跨线程访问做检查
    3. 第二种办法: 使用delegate和invoke来从其他线程中调用控件
    4. 第三种办法: 使用delegate和BeginInvoke来从其他线程中控制控件
    5. 第四种办法: 使用BackgroundWorker组件
    6. 源代码下载

     

    线程间操作无效

    界面上有一个button和一个label,  点击button会启动一个线程来更新Label的值

    复制代码
            private void button1_Click(object sender, EventArgs e)
            {
                Thread thread1 = new Thread(new ParameterizedThreadStart(UpdateLabel));
                thread1.Start("更新Label");
            }
    
            private void UpdateLabel(object str)
            {
                this.label1.Text = str.ToString();
            }
    复制代码

    运行后, 程序会报错 "跨线程操作无效,从不是创建"label1"的线程访问它"

     

    这是因为.NET禁止了跨线程调用控件, 否则谁都可以操作控件,最后可能造成错误。   

     

    下面介绍几种跨线程调用控件的方法

     

    第一种办法:禁止编译器对跨线程访问做检查

    这是最简单的办法, 相当于不检查线程之间的冲突,允许各个线程随便乱搞,最后Lable1控件的值是什么就难以预料了 (不推荐使用这种方法)

            public Form1()
            {
                InitializeComponent();
                // 加入这行
                Control.CheckForIllegalCrossThreadCalls = false;
            }

     

    第二种办法: 使用delegate和invoke来从其他线程中调用控件

    调用控件的invoke方法,就可以控制控件了,例如

    复制代码
            private void button2_Click(object sender, EventArgs e)
            {
                Thread thread1 = new Thread(new ParameterizedThreadStart(UpdateLabel2));
                thread1.Start("更新Label");
            }
    
            private void UpdateLabel2(object str)
            {
                if (label2.InvokeRequired)
                {
                    // 当一个控件的InvokeRequired属性值为真时,说明有一个创建它以外的线程想访问它
                    Action<string> actionDelegate = (x) => { this.label2.Text = x.ToString(); };
                    // 或者
                    // Action<string> actionDelegate = delegate(string txt) { this.label2.Text = txt; };
                    this.label2.Invoke(actionDelegate, str);
                }
                else
                {
                    this.label2.Text = str.ToString();
                }
            }
    复制代码

     

    第三种办法: 使用delegate和BeginInvoke来从其他线程中控制控件

    只要把上面的 this.label2.Invoke(actionDelegate, str); 中的 Invoke 改为BeginInvoke方法就可以了

    Invoke方法和BeginInvoke方法的区别是

    Invoke方法是同步的, 它会等待工作线程完成,

    BeginInvoke方法是异步的, 它会另起一个线程去完成工作线程

     form.Invoke((Action)(() =>
                            {
                                form.Text = "数据传送完成,正在写入Flash";

                            }));

    第四种办法: 使用BackgroundWorker组件(推荐使用这个方法)

    BackgroundWorker是.NET里面用来执行多线程任务的控件,它允许编程者在一个单独的线程上执行一些操作。耗时的操作(如下载和数据库事务)。用法简单 

    复制代码
            private void button4_Click(object sender, EventArgs e)
            {
                using (BackgroundWorker bw = new BackgroundWorker())
                {
                    bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
                    bw.DoWork += new DoWorkEventHandler(bw_DoWork);
                    bw.RunWorkerAsync("Tank");
                }         
            }
    
            void bw_DoWork(object sender, DoWorkEventArgs e)
            {       
                // 这里是后台线程, 是在另一个线程上完成的
                // 这里是真正做事的工作线程
                // 可以在这里做一些费时的,复杂的操作
                Thread.Sleep(5000);
                e.Result = e.Argument + "工作线程完成";
            }
    
            void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
            {
                //这时后台线程已经完成,并返回了主线程,所以可以直接使用UI控件了 
                this.label4.Text = e.Result.ToString(); 
            }
    复制代码

    转载于:https://www.cnblogs.com/yuesebote/p/10879775.html

    展开全文
  • C#编程中跨线程访问控件一、简述二、Winforms中跨线程访问控件三、WPF中跨线程访问控件参考文档 一、简述 C#中不允许跨线程直接访问界面控件,即一个线程中如主线程创建的控件不允许被其他线程例如子线程直接访问,...

    一、简述

    C#中不允许跨线程直接访问界面控件,即一个线程中如主线程创建的控件不允许被其他线程例如子线程直接访问,如果直接访问或设置属性则会爆出“调用线程无法访问此对象,因为另一个线程拥有该对象”等类似错误。
    在一个线程中设置其他线程所有的控件属性通常有两种方法,一是设置System.Windows.Forms.Control的CheckForIllegalCrossThreadCalls属性值为false,表示不对错误线程的调用进行捕捉,这种方法只对winforms界面框架有效,在WPF中无法设置该属性,只能使用第二种方法。
    第二种方法是通过委托来实现控件属性设置,需要通过InvokeBeginInvoke来实现,Invoke表示同步,BeginInvoke表示异步,下面列举了在winforms中和WPF两种界面框架中跨线程访问控件的代码示例。

    二、Winforms中跨线程访问控件

    一般的委托方法示例代码如下:

    delegate void delegateSetText(string str);//定义一个委托
    private void SetText(string str)
    {
      if (InvokeRequired)//判断是否是被其他线程调用
       {
           delegateSetText delegatesetText01 = new delegateSetText(SetText);
           Invoke(delegatesetText01, new object [] {str});
           return;
       }
       textBox01.Text = str;
    }
    

    也可以采用匿名代理的方式,示例代码如下:

    delegate void delegateSetText(string str);//定义一个委托
    private void SetText(string str)
    {
      delegateSetText delegatesetText01 = delegate(string str01)
       {
           textBox01.Text = str01;
       }
       Invoke(delegatesetText01, new object [] {str});
    }
    

    三、WPF中跨线程访问控件

    在WPF中跨线程访问控件需要使用Dispatcher。Dispatcher是WPF中的线程调度管理器,用在子线程刷新主线程(UI线程)(比如绑定的时候,属性更新的时候),在子线程里面起一个dispatcher,将工作项目调度到 UI 线程,让主线程调度刷新UI的代码。示例代码如下:

    private void SetText(string str)
    {
      if (!Dispatcher.CheckAccess())//判断是否是被其他线程调用
       {
           Dispatcher.Invoke(() => SetText(str));
           return;
       }
       textBox01.Text = str;
    }
    

    参考文档

    C#中Invoke的用法()
    不支持从调度程序线程以外的线程对其 SourceCollection 进行的更改
    【C#】调用线程无法访问此对象,因为另一个线程拥有该对象
    InvokeRequired和Invoke
    InvokeRequired in wpf [duplicate]
    C# 跨线程调用TextBox方法浅析 利用SetTextCallback方法

    展开全文
  • 跨线程访问控件

    2017-12-26 18:27:05
    介绍多线程的使用,跨线程访问控件,修改控件属性 代码实现:  ///  /// 点击刷新界面显示数字-跨线程赋值文本框信息  ///  /// The source of the event.  /// The instance containing the event ...
  • C#跨线程访问控件

    2013-03-17 14:28:48
    C#跨线程访问控件,用了线程池和Action委托和Control的Invoke方法
  • WinForm跨线程访问解决

    千次阅读 2018-11-07 10:48:52
    解决控件跨线程访问的问题 public partial class MainFrm : Form { public MainFrm() { InitializeComponent(); //解决跨线程访问无效方式 //方法一:称之为-掩耳盗铃方法 // 真正项目中绝对不能这么做 //...
  • 用C#写的双色球查询字典子线程查询以及跨线程访问控件
  • WPF中UI元素跨线程访问

    千次阅读 2018-11-14 16:33:14
    C#中跨线程访问UI dotnet中线程资源独占UI元素,不能跨线程访问,可以通过Dispatcher.Invoke的方式调用,但实际处理还是UI线程中,任务量比较大的数据会增加线程的处理压力。 其实还有一种做法,可以通过设置UI元素...
  • C#中跨线程访问控件

    2019-10-07 23:57:12
    第二种方法是禁止编译器对跨线程访问作检查,可以实现访问,但是出不出错不敢保证Control.CheckForIllegalCrossThreadCalls = false; 最近我在做一个项目,遇到了跨线程要去访问页面控件.但是总是提示出错,不能在...
  • .net原则上禁止跨线程访问控件,因为这样可能造成错误的发生,有一种方法是禁止编译器对跨线程访问作检查,Control.CheckForIllegalCrossThreadCalls=false;可以实现访问,但是出不出错不敢保证C#跨线程访问控件运行...
  • .net 2.0以后加强了安全机制,不允许在winform中直接跨线程访问控件的属性,会提示错误“跨线程操作无效“。 提供几种方法解决这个问题 1. 设置CheckForIllegalCrossThreadCalls为False ...
  • WinForm-跨线程访问判定方法=InvokeRequired方法介绍调用示例 方法=InvokeRequired // 摘要: // Gets a value indicating whether the caller must call an invoke method when making // method calls to the ...
  • winform跨线程访问控件

    2018-10-30 15:00:00
    首先说下,.net 2.0以后加强了安全机制,不允许在winform中直接跨线程访问控件的属性。所以除了控件所在的线程外的线程调用会抛异常 (Cross-thread operation not valid:Control 'textBox1' accessed from a ...
  • 跨线程访问本质是 对线程进行上锁,NSCondition  直接上代码。 @interface ViewController () {  NSCondition * _condition; //条件锁 // NSInteger _index; } //@property (nonatomic, strong) ...
  • Unity跨线程访问类实现

    千次阅读 2018-04-28 10:53:35
    Unity跨线程访问类实现 unity中子线程无法使用unity中的方法,但很多时候我们需要在子线程中调用unity的方法(比如网络游戏),为了解决这个问题,我们就必须将需要在子线程调用的unity方法的代码,在主线程中执行...
  • WinForm跨线程访问控件异常 最近做了个WinForm的小项目,遇到个简单的问题记录下。需求:点击”下载“,显示正在下载,下载完后更新状态为”ready“(要求用多线程,避免前台卡死)。 做法 新建一个线程,在新线程中...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,972
精华内容 788
关键字:

跨线程访问