精华内容
下载资源
问答
  • .NET WinForm跨线程访问控件三种方式
    2021-04-06 16:08:46
    public partial class Form1 : Form
    {
        int index = 0;
        public Form1()
        {
            // 方法1
            //System.Windows.Forms.Control.CheckForIllegalCrossThreadCalls = false;
            InitializeComponent();
        }
        private void button1_Click(object sender, EventArgs e)
        {
            // 方法2
            //using (BackgroundWorker bw = new BackgroundWorker())
            //{
            //    bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
            //    bw.DoWork += new DoWorkEventHandler(bw_DoWork);
            //    bw.RunWorkerAsync("Tank");
            //}
    
            // 方法3
            //Task.Run(() =>
            //{
            //    while (true)
            //    {
            //        index++;
            //        SetAppendTB(this.textBox1, index + "\r\n");
            //        Thread.Sleep(100);
            //    }
            //});
        }
    
        public delegate void SetText(Control tb, string str);
        private void SetAppendTB(Control tb, string str)
        {
            if (tb.InvokeRequired)//判断是不是跨线程 true是 false不是
            {
                SetText setText = new SetText(SetAppendTB);//实例化委托对象
                Invoke(setText, new object[] { tb, str });//线程传递
            }
            else
            {
                tb.Text = str;//赋值操作 可自行替换
            }
        }
    
        void bw_DoWork(object sender, DoWorkEventArgs e)
        {
            // 这里是后台线程, 是在另一个线程上完成的
            // 这里是真正做事的工作线程
            // 可以在这里做一些费时的,复杂的操作
            Thread.Sleep(5000);
            e.Result = e.Argument + "工作线程完成";
        }
    
        void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            //这时后台线程已经完成,并返回了主线程,所以可以直接使用UI控件了
            this.textBox1.Text = e.Result.ToString() + "\r\n";
        }
    }

     

    更多相关内容
  • 可以这样认为:不能跨线程直接访问控件; 最简单的办法就是: 代码如下:using System.Windows.Forms; Parent.Invoke(new MethodInvoker(delegate { Parent.label1.Text = “成功” ; }));其中,“Parent”是主...
  • 使用delegate和Invoke,使用delegate和BeginInvoke,使用BackgroundWorker组件,使用SynchronizationContext组件
  • 多个线程竞争读写同一个资源往往会造成意想不到的意外结果,UI界面也是一种资源,所以跨线程修改UI界面往往被加以限制。这里采用Task + MethodInvoker的方式完成跨线程对UI对的修改。
  • C# winform跨线程操作控件

    前提:当我们使用Winform开发的时候,经常会遇到:System.InvalidOperationException:“线程间操作无效: 从不是创建控件“xxxx”的线程访问它。”
    原因:发生次异常的原因是因为winform在渲染UI界面和操作界面数据的时候使用的是同一个线程。当我们创建另外一个线程,去操作此线程的UI控件,会导致线程不安全。winform为了防止线程不安全,因此杜绝了这个跨线程操作,并且抛出异常。

    异常举例:创建两个控件,一个是按钮控件,一个是lable控件

    private void button1_Click(object sender, EventArgs e)
            {
                Thread thread = new Thread(()=>
                {
                    if (this.InvokeRequired)
                    {
                        this.Invoke(new Action(() =>
                        {
                            lable1.Text = "Hello Thread!";
                        }));
                    }
                }
                );
                thread.IsBackground = true;
                thread.Start();
            }
    

    当执行此按钮的时候,会导致跨线程操作异常。

    解决方案:
    使用InvokeRequired属性,判断是否是线程安全。

    if (this.InvokeRequired) 
    {
    	this.Invoke(new Action(() =>
    	{
    		lable1.Text = "Hello World!";
    	}));
    }
    else
    {
    	lable1.Text = "Hello World!";
    }
    
    展开全文
  • 主要介绍了C#之WinForm跨线程访问控件,实例讲述了跨线程访问控件的简单实现方法与用法,需要的朋友可以参考下
  • C# WinForm跨线程访问UI控件

    C# 跨线程访问控件

    在做WinForm时,在UI线程之外调用控件会报异常:System.InvalidOperationException:“线程间操作无效: 从不是创建控件“label1”的线程访问它。”
    跨线程访问控件异常

    我们只需在跨线程调用控件时增加如下代码:

    if (this.InvokeRequired) 
    {
    	this.Invoke(new Action(() =>
    	{
    		lable1.Text = "Hello World!";
    	}));
    }
    

    如下是我的demo
    在这里插入图片描述

    using System;
    using System.Threading;
    using System.Threading.Tasks;
    using System.Windows.Forms;
    
    namespace test
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }
    
            private void ChangeControl()
            {
                if (this.InvokeRequired)
                {
                    this.Invoke(new Action(() =>
                    {
                        lbl_msg.Text = "Hello Task!";
                    }));
                }
            }
            private void btnTask_Click(object sender, EventArgs e)
            {
                Task.Run(()=> {
                    ChangeControl();
                });
    
            }
    
            private void btnThread_Click(object sender, EventArgs e)
            {
                Thread thread = new Thread(()=>
                {
                    if (this.InvokeRequired)
                    {
                        this.Invoke(new Action(() =>
                        {
                            lbl_msg.Text = "Hello Thread!";
                        }));
                    }
                }
                );
                thread.IsBackground = true;
                thread.Start();
            }
        }
    }
    

    程序运行结果
    在这里插入图片描述

    在这里插入图片描述

    展开全文
  • 线程间操作无效: 从不是创建控件的线程访问它。当我们执行C#程序出现此错误提示时,可以采用委托的方法来解决,但是有个重要问题需要注意...本例程提供了跨线程安全调用控件的方法。
  • WINFORM 跨线程通信

    2021-12-30 11:25:00
    场景:winform 操控射频读写器,控件回调显示交互结果,指令下发后回叫是委托,那线程间通信就是个问题,。 网上看了一个侦听端口的 (源地址找不见了,好像是supersocket的一个例子) using System; using System...

    做个记号,先。后面再总结。
    环境:.NET fx4.7 .NET standard 2
    场景:winform 操控射频读写器,控件回调显示交互结果,指令下发后回叫是委托,那线程间通信就是个问题,。

    网上看了一个侦听端口的
    (源地址找不见了,好像是supersocket的一个例子)

    using System;
    using System.Collections.Generic;
    
    namespace SSClient
    {
        public class LogHelper
        {
            public delegate void LogEvent(string msg);
            public static List<string> allLines = new List<string>();
            public static int displayLength = 0;
            private static LogEvent OnLog { get; set; }
    
            /// <summary>
            /// winform使用后台线程写显示Log
            /// </summary>
            public static void SetOnLog(LogEvent e)
            {
                OnLog = e;
                //每100毫秒重新渲染到界面
                var timer = new System.Timers.Timer(100);
                timer.Elapsed += new System.Timers.ElapsedEventHandler((s, x) => 
                {
                    try
                    {
                        int count = allLines.Count;
                        if (displayLength == count)
                            return;
                        //最多保留Log行数
                        if (allLines.Count > 5000) 
                            allLines.RemoveRange(0, 20);
    
                        displayLength = allLines.Count;
                        OnLog(string.Join("\r\n", allLines));
                    }
                    catch { }
                });
                timer.Enabled = true;
                timer.Start();
            }
            /// <summary>
            /// 普通的文件记录日志
            /// </summary>
            /// <param name="info"></param>
            public static void WriteLog(string info)
            {
                if (OnLog != null)
                {
                    allLines.Add(string.Join(" ", DateTime.Now.ToString("HH:mm:ss"), info));
                }
            }
            /// <summary>
            /// 错误日志
            /// </summary>
            /// <param name="info"></param>
            /// <param name="se"></param>
            public static void WriteLog(string info, Exception se)
            {
                if (OnLog != null)
                {
                    allLines.Add(info);
                }
            }
        }
    }
    

    定义一个处理回显的

            public Form1()
            {
                InitializeComponent();
                CheckForIllegalCrossThreadCalls = false;
            }
    
            private void Form1_Load(object sender, EventArgs e)
            {
    
                LogHelper.SetOnLog(new LogHelper.LogEvent((m) =>
                {
                    txtAll.Text = txtAll.Text = (m + "\r\n"); 
                    txtAll.Select(txtAll.TextLength, 0);
                    txtAll.ScrollToCaret();
                }));
            }

    CheckForIllegalCrossThreadCalls = false;

     有这句,有没有LogHelper没差。也是个不安操作,有什么不安,先搁一边再试一下另一个方法InvokeRequired...

    //CheckForIllegalCrossThreadCalls = false;
    
            private delegate void WriteLogUnSafe(TextBox textboxLog, string msg);
            public void Log(TextBox textboxLog, string msg) 
            {
                //LogHelper.WriteLog(msg);
    
                if (this.InvokeRequired)
                {
                    WriteLogUnSafe InvokeWriteLog = new WriteLogUnSafe(Log);
                    this.Invoke(InvokeWriteLog, new object[] { textboxLog, msg });
                }
                else
                {
                    txtContainer.AppendText(msg + "\r\n");
                }
            }

    工作的很好,怎么解释,容某想想。。

    想到一个处理方式,收到信息后存在公共变量中,让变量的变化触发委托,一搜就找到一段,

    public   delegate   void   delegateHandler();   
      public   class   my   
      {   
            public   int   i=0;   
            public   delegateHandler   myhandle;   
            public   int   changeI   
            {   
                      get{return   i;}   
                      set{   
                              i=value;   
                              myhandle();   
                              }   
              }   
      }   
        
      public   class   otherclass   
      {   
            public   my   o;   
            public   otherclass()   
      {       o=new   my();   
      }   
      pulic   void   init()   
      {   
            o.myhandle+=new   delegateHandler(howtodeal);   
      }   
      public   void   howtodeal()   
      {   
            //你自己的处理程序   
      }   
              
        
      }

    下周试试。
     

    展开全文
  • WinForm跨线程访问解决

    千次阅读 2018-11-07 10:48:52
    解决控件跨线程访问的问题 public partial class MainFrm : Form { public MainFrm() { InitializeComponent(); //解决跨线程访问无效方式 //方法一:称之为-掩耳盗铃方法 // 真正项目中绝对不能这么做 //...
  • 背景 在我做WinForm开发的过程中,经常会遇到耗时操作或阻塞操作...而在Winform中,跨线程修改UI界面同样是不被允许的。在子线程中修改界面控件时Visual Studio会报出如下错误: 解决思路 .Net提供了很多跨..
  • .net 2.0以后加强了安全机制,不允许在winform中直接跨线程访问控件的属性,会提示错误“跨线程操作无效“。 提供几种方法解决这个问题 1. 设置CheckForIllegalCrossThreadCalls为False ...
  • Winform跨线程操作控件

    2019-09-19 14:24:09
    出于安全考虑,Winform中默认不允许在一个线程中操作另一个线程中的控件,线程同时运行时,两个线程同时访问某一控件,两个线程之间可能会发生死锁。为了区别是否是创建该控件的线程访问该控件,Windows窗体控件中的...
  • C# Winform 跨线程更新UI控件常用方法总结(转) 出处:http://www.tuicool.com/articles/FNzURb 概述 C#Winform编程中,跨线程直接更新UI控件的做法是不正确的,会时常出现“线程间操作无效: 从不是创建控件的...
  • C# WinForm 跨线程访问控件(实用简洁写法)

    千次阅读 多人点赞 2018-11-20 14:56:59
    C# WinForm 跨线程访问控件 在做WinFrom开发的时候,经常会遇到跨线程访问控件的问题,即从不是创建控件的线程去访问控件。百度里面搜索,会有各种各样的解决方案。在诸多方案中,我认为没有一个方案是特别简单,...
  • Winform跨线程操作

    2018-05-15 11:51:47
    在我们常规开发中,经常会遇到需要跨窗体访问的情况,或者在使用多线程的时候需要跨线程访问数据,虽然有很多处理跨线程的方法,但是大多麻烦。 这为大家提供一个跨线程访问的方式。 Invoke(new Action(() =&...
  • 当不跨线程时,使用正常。使用子线程操作webBrowser控件时出现了一下错误。  子线程中对窗体上的控件操作是会出现异常,这是由于子线程和运行窗体的线程是不同的空间所导致的。对于一般的控件,当子线程操作控件...
  • 在多线程操作WinForm窗体上的控件时,出现“线程间操作无效:从不是创建控件XXXX的线程访问它”,那是因为默认情况下,在Windows应用程序中,.NET Framework不允许在一个线程中直接操作另一个线程中的控件(因为访问...
  • 最近在做一个简单点的winform项目的时候,因为要在子线程中控制主线程UI显示日志,在停止线程的时候竟然出现所有线程卡死的情况,这下疯了,难道我做游戏久了,竟然连简单的winform跨线程都不会了么?请看代码,大家看看...
  • winfrom中不允许直接跨线程调用控件的方法 例如 一个udp线程,一个Form窗口线程,希望通过接收的消息创建UI,但是udp线程直接调用Form里的创建UI控件的方法时,会报错此时需要使用形如 if (flowLayoutPanel_Machine...
  • 我们可以使用invoke和bengininvoke invoke同步执行一个委托 begininvoke异步执行一个委托 转载于:https://www.cnblogs.com/birdofparadise/p/7079113.html
  • WINFORM跨线程访问控件

    2021-01-13 09:04:52
    //通过跨线程给控件赋值 private void btnExecute1_Click(object sender, EventArgs e) { Thread thread = new Thread(() => { for (int i = 0; i < 10; i++) { // this.lblR..
  • 博主刚接触线程没多久,需要实现将线程中计算出的数据传递给winform的label显示出来,但是C#中禁止跨线程直接访问控件,首先想到方法一(用委托实现) : 具体拿一个案例(内部计算已省略)说明:需要实现,按button ...
  • Winform跨线程访问控件

    2019-12-20 08:47:02
    采用以下代码,可以方便的在子线程中访问主线程控件 BeginInvoke(new Action(() => { //访问主线程控件的代码 }));
  • 四种方式 C# 线程调用主线程方法,修改主线程控件值。SynchronizationContext、Invoke/BegainInvoke、BackgroundWorker、Thread Crossing

空空如也

空空如也

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

winform跨线程