c#中 线程访问控件的解决方法 可直接调用此方法

问题

由于在初学c#的时候 使用了 线程委托去执行函数,是为了不让软件窗体假死。所以使用下方代码:

Thread th = new Thread(Getform); //创建线程
th.Start();

在使用前需要引入 : using System.Threading;

但是,在Getform 函数中,我调用了修改窗体控件内容的命令。

textbox.text="假";

直接报错了。

线程间操作无效: 从不是创建控件“textbox”的线程访问它

好吧。查找资料,进行查看解决方法、

解决方法:

1、直接忽略线程权限的检查。

public Form1()
{
InitializeComponent();
Control.CheckForIllegalCrossThreadCalls = false;
}

我们加入了这段代码:Control.CheckForIllegalCrossThreadCalls = false; //忽略线程权限检查

个人理解:这样直接忽略也可能有其他的问题,所以大家都是不推荐的,但是也确实在某些时候可以使用,毕竟 方便。。。

2、使用委托进行安全的修改,使用delegate和invoke来从其他线程中控制控件信息(网络复制说明)

网络上的代码 直接复制在C#中查看更加明显

public partial class Form1 : Form
{
private delegate void FlushClient();//代理
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
Thread thread = new Thread(CrossThreadFlush); 

thread.IsBackground=true;
thread.Start();
} 

private void CrossThreadFlush()
{
//将代理绑定到方法
FlushClient fc = new FlushClient(ThreadFuntion);
this.BeginInvoke(fc);//调用代理
}
private void ThreadFuntion()
{
while (true)
{
this.textBox1.Text = DateTime.Now.ToString();
Thread.Sleep(1000);
}
}
}

看起来还是相对很简单的,只是这种会让窗口无响应,因为在无限的刷新窗口,但是。会不会有更好的处理方法呢。

最终的解决方法:

private void button1_Click(object sender, EventArgs e)
        {
            var th = new Thread(() =>
            {
                //label1.Enabled = false;
                label1.CrossThreadCalls(() => { label1.Enabled = !label1.Enabled; });
                WriteMessage(DateTime.Now.ToString());
            });
            th.IsBackground = true;
            th.Start();
        }

        public void WriteMessage(string msg)
        {
            label1.CrossThreadCalls(() =>
            {
                label1.Text = msg;
            });
        }

在使用前,我们新建一个类。

using System.Threading;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
   public static class Class1
    {
       /// <summary>
       /// 跨线程访问控件 在控件上执行委托
       /// </summary>
       /// <param name="ctl">控件</param>
       /// <param name="del">执行的委托</param>
       public static void CrossThreadCalls(this Control ctl, ThreadStart del)
       {
           if (del == null) return;
           if (ctl.InvokeRequired)
               ctl.Invoke(del, null);
           else
               del();
       }
    }
}

  

最终,我们得出了这种解决方法。还算是不错。

我只是在学习过程中记录,欢迎大家探讨

原文地址:http://www.lazyw.org/weituo.html

时间: 2024-10-08 00:19:18

c#中 线程访问控件的解决方法 可直接调用此方法的相关文章

C# 跨线程访问控件的解决方法

public partial class Form1 : Form     {         public Form1()         {             InitializeComponent();             //方法一:不进行跨线程安全检查             //System.Windows.Forms.Control.CheckForIllegalCrossThreadCalls = false;         }         private voi

WinForm跨线程访问控件异常

WinForm跨线程访问控件异常 最近做了个WinForm的小项目,遇到个简单的问题记录下.需求:点击"下载",显示正在下载,下载完后更新状态为"ready"(要求用多线程,避免前台卡死). 做法 新建一个线程,在新线程中下在更新控件状态,报异常跨线程程访问控件(当然可以通过关闭跨线程访问控件检验解决,不鼓励这么做).应该C#5.0版本添加的任务Task异步,这里用异步解决. Code 新建WinForm 项目,Form1添加控件如图 后台代码 private vo

c#使用MethodInvoker解决跨线程访问控件

功能函数测试集锦(77)  C#专区(114)  版权声明:本文为博主原创文章,未经博主允许不得转载. .net 原则上禁止跨线程访问控件,因为这样可能造成错误的发生,有一种方法是禁止编译器对跨线程访问作检查,Control.CheckForIllegalCrossThreadCalls = false;可以实现访问,但是出不出错不敢保证C#跨线程访问控件运行时错误. 使用MethodInvoker即可解决: 原代码: private void btnOK_Click(object sender

C#之Winform跨线程访问控件

C#中禁止跨线程直接访问控件,InvokeRequired是为了解决这个问题而产生的,当一个控件的InvokeRequired属性值为真时,说明有一个创建它以外的线程想访问它.此时它将会在内部调用new MethodInvoker(LoadGlobalImage)来完成下面的步骤,这个做法保证了控件的安全,你可以这样理解,有人想找你借钱,他可以直接在你的钱包中拿,这样太不安全,因此必须让别人先要告诉你,你再从自己的钱包把钱拿出来借给别人,这样就安全了 ----------------------

2 跨线程访问控件InvokeHelper类

这里是一张动画,演示在多线程(无限循环+Thread.Sleep)情况下主界面操作不受影响. 多线程是一种提高程序运行效率和性能的常用技术.随着我们学习工作的深入,在编程中或多或少会涉及到需要多线程的情况.多数时候,我们的操作模式是后台线程中处理数据,计算结果,然后在前台界面(GUI)中更新显示. 在.NET Framework中,为了保证线程安全,避免出现访问竞争等问题,是不允许跨线程访问窗体控件的.如果强行访问,则会引发InvalidOperationException无效操作异常,如下图:

C# WinFrom 跨线程访问控件

1.跨线程访问控件委托和类的定义 using System; using System.Windows.Forms; namespace ahwildlife.Utils { /// <summary> /// 跨线程访问控件的委托 /// </summary> public delegate void InvokeDelegate(); /// <summary> /// 跨线程访问控件类 /// </summary> public class Invok

C#中线程对控件的访问

Control类提供了一个Invoke方法来给子线程访问主线程的控件,它的原型是酱紫的: object.Control.Invoke(Delegate method); object.Control.Invoke(Delegate method,params object[] args); method是已创建的委托对象,如果该对象的关联方法有参数,那就放在数组args中,没有就不用传 Invoke食用方法如下(假设我访问控件的方法是getForms()): public delegate vo

跨线程访问控件解决办法

在多线程中访问控件有两种方式 方式1: 取消对跨线程操作的检查 在 from 的构造 函数中增加 system.window.forms.control.CheckForIllegalCrossThreadCalls=false; 方式2 : 采用委托的形式作为代理通知主线程控件,允许访问. delegate void   showData(string para); visistControl(string para) { if (this.textbox1.invokeRequered) /

跨线程访问控件的问题和编程方法

很多时候写windows程序都需要结合多线程,经常会跨线程操作控件,这时就会出错,提示不允许"从不是创建控件的进程访问它". 这个时候的解决思路:把想对另一线程中的控件实施的操作放到一个函数中,然后使用delegate代理那个函数,并且在那个函数中加入一个判断,用InvokeRequired来判断调用这个函数的线程是否和控件线程在同一线程中,如果是则直接执行对控件的操作,否则利用控件的Invoke或BeginInvoke方法来执行这个代理,执行唤醒控件的操作.Invoke的中文解释是唤