在开发winfrom应用时,经常遇到异常:System.InvalidOperationException:“线程间操作无效: 从不是创建控件“xxxx”的线程访问它。出现这个异常的原因是创建这个UI的线程,和当前访问这个UI的线程不会是同一个。Winform为了防止线程不安全,因此对这个跨线程访问抛出异常,禁止这个操作。

解决方案

使用InvokeRequired属性判断是否线程安全。

            if (richTextBox1.InvokeRequired)
{
richTextBox1.Invoke(new Action(() =>
{
richTextBox1.AppendText(log);
richTextBox1.AppendText("\r\n");
}));
}
else
{
richTextBox1.AppendText(log);
richTextBox1.AppendText("\r\n");
}

如果richTextBox1是在非主线程创建或找不到其句柄,那么richTextBox1.InvokeRequired=false返回false,就会走else分支,如果在找不到句柄的情况下,else里的代码也会抛异常。为了更加安全,需要进一步对句柄进行判断,用IsHandleCreated判断是否创建了句柄。

            if (richTextBox1.InvokeRequired)
{
richTextBox1.Invoke(new Action(() =>
{
richTextBox1.AppendText(log);
richTextBox1.AppendText("\r\n");
}));
}
else
{
if (richTextBox1.IsHandleCreated)
{
richTextBox1.AppendText(log);
richTextBox1.AppendText("\r\n");
} }

上面代码基本上没什么问题了。但是稍显麻烦,可以进行精简一下。使用哦当前FormInvoke方法而不是具体某个ControlInvoke,这样能确保当前的操作一定在当前的UI线程中,且句柄一并被创建。

        private void Log(string log)
{
Invoke(new Action(() =>
{
richTextBox1.AppendText(log);
richTextBox1.AppendText("\r\n");
}));
}

其实在winform中跨线程访问UI很常见,比如在一个子窗口中进行了某个操作,需要更新主窗口里的某些状态或数据,如果稍不注意就会出现跨线程访问UI的异常,因此Invoke方法应该被广泛使用。

Winform跨线程访问UI的更多相关文章

  1. WPF / Win Form:多线程去修改或访问UI线程数据的方法( winform 跨线程访问UI控件 )

    WPF:谈谈各种多线程去修改或访问UI线程数据的方法http://www.cnblogs.com/mgen/archive/2012/03/10/2389509.html 子线程非法访问UI线程的数据 ...

  2. C# 委托 / 跨线程访问UI / 线程间操作无效: 从不是创建控件“Form1”的线程访问它

    C# 委托 / 跨线程访问UI /  线程间操作无效: 从不是创建控件“Form1”的线程访问它 网上的代码都比较复杂,还是这个简单 见代码, 简易解决办法: 主窗体代码 using System; ...

  3. 跨线程访问UI控件时的Lambda表达式

    工作中经常会用到跨线程访问UI控件的情况,由于.net本身机制,是不允许在非UI线程访问UI控件的,实际上跨线程访问UI控件还是 将访问UI的操作交给UI线程来处理的, 利用Control.Invok ...

  4. C# 跨线程访问UI不报错,必须使用Invoke。

    代码有时跨线程访问UI,修改按钮Enable属性不报异常.调试发现修改按钮属性的线程是Background,执行不报异常. 在窗体构造中添加 Control.CheckForIllegalCrossT ...

  5. .NET设计篇08-线程统一取消模型和跨线程访问UI

    知识需要不断积累.总结和沉淀,思考和写作是成长的催化剂,输出倒逼输入 内容目录 一.线程统一取消模型1.取消令牌2.可以中断的线程1.设计一个中断函数2.创建CancellationTokenSour ...

  6. .NET设计篇08-线程取消模型和跨线程访问UI

    知识需要不断积累.总结和沉淀,思考和写作是成长的催化剂,输出倒逼输入 内容目录 一.线程统一取消模型1.取消令牌2.可以中断的线程1.设计一个中断函数2.创建CancellationTokenSour ...

  7. C# Winform 跨线程更新UI控件常用方法汇总(多线程访问UI控件)

    概述 C#Winform编程中,跨线程直接更新UI控件的做法是不正确的,会时常出现“线程间操作无效: 从不是创建控件的线程访问它”的异常.处理跨线程更新Winform UI控件常用的方法有4种:1. ...

  8. C# Winform 跨线程更新UI控件常用方法总结(转)

    出处:http://www.tuicool.com/articles/FNzURb 概述 C#Winform编程中,跨线程直接更新UI控件的做法是不正确的,会时常出现“线程间操作无效: 从不是创建控件 ...

  9. C#-WinForm跨线程修改UI界面

    待解决的问题 在我做WinForm开发的过程中,经常会遇到耗时操作或阻塞操作.他们会引发软件的卡顿甚至假死,严重影响软件的使用. 因此,这类耗时或阻塞的操作一般都会使用异步的方式去执行,不影响主线程( ...

  10. C# WinForm 跨线程访问控件

    问题出现: 在WinForm 处理多线程访问主线程的控件时候,就会出现如图所示的错误对话框:    解决方案:  方案一:去掉线程访问主线程UI控件的安全检查,使用: Control.CheckFor ...

随机推荐

  1. AssertionError: Expected a `Response`, `HttpResponse` or `HttpStreamingResponse` to be returned from

    函数里面return response问题: 1.没有 2.写错 3.位置错 例如: return Response('确认成功')

  2. 【Vue2.x源码系列08】Diff算法原理

    什么是虚拟DOM DOM是很慢的,其元素非常庞大,当我们频繁的去做 DOM更新,会产生一定的性能问题,我们可以直观感受一下 div元素包含的海量属性 在Javascript对象中,虚拟DOM 表现为一 ...

  3. django之drf(部分讲解)

    序列化类常用字段和字段参数 drf在Django字段类型的基础上派生了自己的字段类型以及字段参数 序列化器的字段类型用于处理原始值和内部数据类型直接的转换 还可以用于验证输入.以及父对象检索和设置值 ...

  4. [vuex] unknown action type:***

    vuex 分模块后使用mapActions调用action老是提示 [vuex] unknown action type:*** 异常 目录 index.js是这样的 import Vue from ...

  5. Java方法的调用以及方法参数传递、方法的递归调用

    一.方法的调用以及方法参数传递 1.方法的定义: ​ 访问修饰符 返回值类型 方法名 ([参数列表]){ ​ 方法体 } 如果方法体中需要一些未知的数据作为执行条件,那么这些数据可以作为参数. 如果方 ...

  6. WC2021及学长分享题目

    部分题目见洛谷题单 动态更新. 标 * 为想做的题. hdhd: CF1214G Feeling Good CF1305F Kuroni and the Punishment AGC016F Game ...

  7. 新版本,ggplot2 v3.3.0 新特性来袭

    ggplot2 迎来了新的版本,官方宣布了一些新的特性.下面一起看看吧. 1. 轴代码重写 这有利于解决轴标签重叠的情况. 2. 新的 scale bin,它可以像使用 color, fill 一样使 ...

  8. Spring Boot异步请求处理框架

    Spring Boot异步请求处理框架 1.前言 ​ 在Spring Boot项目中,经常会遇到处理时间过长,导致出现HTTP请求超时问题,状态码:502. ​ 例如一个文件导入接口需要导入一个Exc ...

  9. Rust 内存系统

    第四章 内存系统 不同的编程语言对内存有着不同的管理方式. 按照内存的管理方式可将编程语言大致分为两类: 手动管理类 手动内存管理类需要开发者使用malloc和free等函数显式管理内存. 自动内存管 ...

  10. Hello Welcome to my blog!

    Hello Welcome to my blog!