今天开发alexSEO软件时,出现了在创建窗口句柄之前,不能在控件上调用 Invoke 或 BeginInvoke。...//BeginInvoke中只能放置操作控件的代码。BeginInvoke将子线程线程通过委托抛向UI主线程 。...当调试运行中突然关闭软件时,labb.Invoke(labchange);语句就出先了“在创建窗口句柄之前,不能在控件上调用 Invoke 或 BeginInvoke。”错误。...第一种应该是界面还来不及响应Invoke,第二种是界面线程已经结束,所以响应不了。...最后解决办法是在labb.Invoke(labchange);前加一个if(labb.IsHandleCreated)判断就可以了。
btnRefresh.Enabled = true; }); 但是假如在多线程操作还没完成的时候,我就提前关闭窗体,则会引发InvalidOperationException,提示 “在创建窗口句柄之前...,不能在控件上调用 Invoke 或 BeginInvoke” ,并且如果没有捕获到,则可能导致程序崩溃,直接关闭。...百度之后,发现需要判断控件的IsHandleCreated和IsDisposed等属性,并且如果还有错误,可以再捕获InvalidOperationException异常,避免程序崩溃 但是在项目中有太多需要修改...method(); } } } 代码中并没有专门捕获InvalidOperationException,因为如代码中这样判断之后,不再会出现 窗口句柄未创建...= true; }); 跟之前的代码差别不大,可直接替换所有跨线程调用UI的代码。
下面我们在来说下.NET中对invoke和begininvoke的官方定义。 control.invoke(参数delegate)方法:在拥有此控件的基础窗口句柄的线程上执行指定的委托。...control.begininvoke(参数delegate)方法:在创建控件的基础句柄所在线程上异步执行指定委托。...解决从不是创建控件的线程访问它 在多线程编程中,我们经常要在工作线程中去更新界面显示,而在多线程中直接调用界面控件的方法是错误的做法,Invoke 和 BeginInvoke 就是为了解决这个问题而出现的...这个主线程维护着整个窗体以及上面的子控件。当它得到一个消息,就会调用DispatchMessage方法派遣消息,这会引起对窗体上的窗口过程的调用。...Invoke或者BeginInvoke方法,通过一个委托把调用封送到控件所属的线程上执行。
在Invoke或者BeginInvoke的使用中无一例外地使用了委托Delegate 一、为什么Control类提供了Invoke和BeginInvoke机制?...这个主线程维护着整个窗体以及上面的子控件。当它得到一个消息,就会调用DispatchMessage方法派遣消息,这会引起对窗体上的窗口过程的调用。...Invoke或者BeginInvoke方法,通过一个委托把调用封送到控件所属的线程上执行。...有些api发送消息需要一个窗口句柄,这种函数可以把消息发送到指定窗口的主线程消息队列;而有些则可以直接通过线程句柄,把消息发送到该线程消息队列中。 ?...返回之前,调用者将会被暂时阻塞。 PostMessage也是一个用来发送消息到窗口消息队列的api函数,但这个方法是非阻塞的。
下面我们在来说下.NET中对invoke和begininvoke的官方定义。 control.invoke(参数delegate)方法:在拥有此控件的基础窗口句柄的线程上执行指定的委托。...control.begininvoke(参数delegate)方法:在创建控件的基础句柄所在线程上异步执行指定委托。...如果你的后台线程在更新一个UI控件的状态后不需要等待,而是要继续往下处理,那么你就应该使用BeginInvoke来进行异步处理。...那么现在我们在回想下invoke(同步)和begininvoke(异步)的概念,其实它们所说的意思是相对于子线程而言的,其实对于控件的调用总是由 主线程来执行的。...解决从不是创建控件的线程访问它 在多线程编程中,我们经常要在工作线程中去更新界面显示,而在多线程中直接调用界面控件的方法是错误的做法,Invoke 和 BeginInvoke 就是为了解决这个问题而出现的
那么在编写程序之前必须要明白的一个点就是窗体的UI的操作只能通过UI线程来执行,其他线程如果要去执行窗体中的控件值修改或者其它【任何和窗体线程相关的操作】,就会报异常,所有人都知道的。...InitializeComponent(); CheckForIllegalCrossThreadCalls = false;//时候捕获对错误线程的调用...然后再看看Invoke,BeginInvoke到底是什么东西: 直接F12找到签名对应的解释 // // 摘要: // 在创建控件的基础句柄所在线程上异步执行指定委托。...// // 异常: // System.InvalidOperationException: // 找不到适当的窗口句柄。...: 拥有此控件的基础窗口句柄的线程上执行执行的委托。
为什么凭空出现了一个可以用来发送消息的窗口?于是,在 Dispatcher 构造函数中发现了这个窗口。...请进入 MessageOnlyHwndWrapper 类看,它的基类 HwndWrapper 中直接使用了方法 UnsafeNativeMethods.CreateWindowEx 创建了这个窗口,然后拿到了它的句柄...所以严格意义上只分了两种——前台优先级和非前台优先级。而区分他们的一个分界点就是——用户的输入。 如果有用户的输入发生,那么会开启一个定时器,在定时器时间到达之前,所有的后台优先级任务都不会去执行。...这样保证了在不阻塞线程的情况下进行“等待”。至于如何做到“不阻塞地等待”,请参阅本系列的第二篇文章 深入了解 WPF Dispatcher 的工作原理(PushFrame 部分)。...总结 进入了 .NET Framework 4.5 及以上的开发者们,建议使用 InvokeAsync 代替 BeginInvoke; Dispatcher 通过创建一个隐藏的消息窗口来让一个个 Invoke
线程关联特征: 大部分WPF控件继承自DispatcherObject,包括Application对象,具有线程关联特征,只有在创建这些对象的线程上操作才是安全的。...此时,这些线程可以使用Dispatcher.Invoke或Dispatcher.BeginInvoke方法。...异步操作: Dispatcher.InvokeAsync方法用于在UI线程上异步执行指定的操作,而不会阻塞调用线程。这使得在处理大量数据或执行耗时操作时,UI线程仍然保持响应性。...Dispatcher执行优先级 DispatcherPriority枚举: Inactive:非活动状态,通常用于不活动的窗口。 SystemIdle:系统空闲时的操作,例如后台计算。...在WPF中,通过 Dispatcher.Invoke 或 Dispatcher.BeginInvoke 方法,可以设置操作的优先级。例如: 常见用途: 不同的操作可能需要不同的优先级。
”基于本机 Win32 窗口,而 Win32 窗口从本质上而言是单元线程。...STA 模型意味着可以在任何线程上创建窗口,但窗口一旦创建后就不能切换线程,并且对它的所有函数调用都必须在其创建线程上发生。...STA 模型要求需从控件的非创建线程调用的控件上的任何方法必须被封送到(在其上执行)该控件的创建线程。...基类 Control 为此目的提供了若干方法(Invoke、BeginInvoke 和 EndInvoke)。Invoke 生成同步方法调用;BeginInvoke 生成异步方法调用。...如果您在控件中为大量占用资源的任务使用多线程,则用户界面可以在背景线程上执行一个大量占用资源的计算的同时保持可响应。 用人话描述为:控件是属于主线程(UI线程),不可以跨线程修改其父级。
隐藏消息窗口 创建时机:在Application的构造函数调用基类DispatcherObject的构造函数的时候,会创建一个Dispatcher对象,在Dispatcher的私有构造函数当中。...WPF也是通过BeginInvoke来解决的,而Wpf的BeginInvoke是在Dispatcher上面暴露了,因为整个消息系统都是Dispatcher在协调。...从上面图可以看出Dispatcher在调用BeginInvoke之后所经历的流程,最终是什么时候Foo()被真正执行的。...第六步,执行DispatcherOperation.Invoke方法,Invoke方法的核心就是调用DispatcherOperation构造时传入的Delegate,也就是Dispatcher.BeginInvoke...而这个过程需要消息不断的流动,就必须加入消息队列,最后还要特定的窗口过程处理,而核心的东西就是这个隐藏的Window1#,他在WPF当中只负责处理异步调用,其他的消息他不关心,剩余的4个窗口在处理。
这篇文章继续讨论,希望在线程和Dispatcher这个点上,能把它讲透。 从哪说起? 按照惯例,在深入问题之前,先找一个插入点,希望这个插入点能为朋友们所理解。 ...这个创建窗口并显示的过程如下: 调用RegisterWindowClass注册窗口类,关联其中的窗口过程WndProc。 调用CreateWindow创建窗口并显示。...Dispatcher的新意 在Winform的消息循环中, 为了线程安全,调用Control的Invoke或者BeginInvoke方法可以在创建控件的线程上执行委托,方法的返回值分别为object...Dispatcher提供了BeginInvoke和Invoke两个方法,其中BeginInvoke的返回值是DispatcherOperation,Invoke函数的内部调用了BeginInvoke,也就是说...用户也可以随时调用Invoke或者BeginInvoke方法加入新的DO,在DispatcherOperation处理的时候也可能会调用BeginInvoke加入新的DO。
在C#中,可以使用System.Threading命名空间中的类(如Thread、ThreadPool、Task等)来创建和管理工作线程,以及使用Control.Invoke或Control.BeginInvoke...你可以通过调用控件的Invoke或BeginInvoke方法在UI线程上执行代码,如果你需要从其他线程访问UI元素。...然而,这样的做法通常是不推荐的,因为控件并不是在主线程上创建的,这可能会导致跨线程操作异常和其他同步问题。在大多数情况下,你应该确保在主线程上创建和操作控件,以确保UI的响应性和同步性。...如果你需要在其他线程上执行与控件相关的操作,应该使用Invoke或BeginInvoke方法在主线程上执行操作。...如果不是,那么你可能需要使用Invoke或BeginInvoke方法在正确的线程上执行操作,唤醒UI线程来对控件内容进行更新,以避免跨线程操作异常。创建控件的线程通常是主线程(UI线程)。
然而,一旦采用多线程,就需要理解 Windows 窗体中最重要的一条线程规则:除了极少数的例外情况,否则都不要在它的创建线程以外的线程中使用控件的任何成员。...此外,这条规则的结果是一个被包含的控件(如,包含在一个表单中的按钮)必须与包含它控件位处于同一个线程中。也就是说,一个窗口中的所有控件属于同一个 UI 线程。...这意味着您不能调用用户界面中任意控件上的任何方法,除非在该方法的文档说明中指出可以调用。该规则的例外情况(总有文档记录)非常少而且它们之间关系也不大。...甚至当出现了一些错误时,在第一次演示程序之前一切看起来也都很正常。...在这种情况下,没必要调用 BeginInvoke,因为我已经处于正确的线程中。调用 Invoke 完全是浪费时间和资源,不如直接调用适当的方法。
invoke方法的初衷是为了解决在某个非某个控件创建的线程中刷新该控件可能会引发异常的问题。...说的可能比较拗口,举个例子:主线程中存在一个文本控件,在一个子线程中要改变该文本的值,此时会有可能引发异常。 为了避免该问题,需要在子线程中使用invoke方法来封装刷新文本内容的函数。...Invoke 或者 BeginInvoke 去调用,两者的区别就是Invoke 会导致工作线程等待,而BeginInvoke 则不会 using System.Threading; public...delegate void MyInvoke(string str);//invoke方法创建委托 private void btnStartThread_Click(object...(mi,new object[]{“abc”}); //调用invoke方法 } public void SetTxt(string str)//委托对应的方法
一个进程可以创建一个或多个线程以执行与该进程关联的部分程序代码。在C#中,线程是使用Thread类处理的, 该类在System.Threading命名空间中。...,thread线程是另外创建的一个线程,在.NET上执行的是托管代码,C#强制要求这些代码必须是线程安全的,即不允许跨线程访问Windows窗体的控件。...”,它封装了对另一个线程中目标对象(窗体控件或其他类)的操作代码。...(3)、触发对象动作 Opt obj.Invoke(doSomeCallBack,arg); 其中Opt obj为目标操作对象,在此假设它是某控件,故调用其Invoke方法。...(同步调用) 6 //action.Invoke("btnAsync_Click_1"); 7 异步调用委托 8 //action.BeginInvoke("
这样的需求应该是很常见的,注重用户体验的开发者都不可能让用户眼巴巴的面对一个卡死掉的界面,所以相信在类似场景中,大家都有各自的处理手段,例如异步执行任务,同时在业务窗体上弄个滚动条什么的,比如这样: ?...是的,更新控件不需要再用ProgressChanged事件,事实上等待窗体实例(一个IWaitForm实例)对调用者是隐藏的,你不能也不需要直接对它操作,一切通过bgwUI进行 如果任务允许被终止,即bgw.WorkerSupportsCancellation...waitForm.BarMinimum = value; } } /// /// 获取或设置取消任务的控件的可见性...就算是现在这样,调用者不小心传入一个已经Close/Dispose的等待窗体也没办法,这个问题WaitUI方案也同样存在,也许后面我会改为仅允许传入等待窗体的Type,完了在方案中全权负责等待窗体的从生到死...总之根本问题就是,当某个窗体在非活动状态下弹出模式窗体,那个模式窗体就会不正常,要问如何才能在非活动状态弹出模式窗体,这个可以自己用timer实现。
在我的认知中,技术视野相对更高,技术范围更广的人写的框架会更好。所以,我认为,[实战]架构师和高级程序员,在本质上没有区别,都是程序员。 只是架构师技术更会好一点,并且接受过项目的洗礼。...也许,人家28岁拿到的机会,你在40岁也可以拿到,不是吗。有机会总比没有强,不是吗。 框架的前期准备 关于框架编写,我不想在Github上放一个源码,然后再写一篇介绍文档。...WPF项目控件(UserControl)以UC作为前缀名创建,如UCTable,UCXXX。 WPF的窗体、页面、控件有且只有一个ViewModel。...在WPF项目中创建WindowMain窗体,并在VM中创建对应的ViewModel。...但Page和UserControl是被Window使用的,不能直接呈现,所以,在使用Page和UserControl之前,我们需要编写MVVM框架中,用于在WPF页面和ViewModel传递信息的Command
Invoke 方法、 Control. BeginInvoke 方法( Control. Invoke 的 异步 版本)、 Control. EndInvoke 方法 以及 Control....2.9 托管资源与非托管资源 > 位置 666 .NET 中 对象 使 用到 的 非 托管 资源 主要 有 I/ O 流、 数据库 连接、 Socket 连接、 窗口 句柄 等 各种 直接 与 操作系统...修饰 的 public 委托 成员, 只 能在 类 外部 进行 附加 和 移 除 操作, 而 调用 操作 只能 发生 在 类型 内部。...这样一来, 我们 在使 用 委托 调用 方法 之前, 需要 先 判断 方法 的 所有者 是否 已经 被 CLR 回收。...7.4 控件 > 位置 2776 无论是 复合 控 件、 扩展 控 件 还是 自定义 控 件, 我们 均可 以 重写 控 件 的 窗口过程:WndProc 虚 方法, 从 根源 上 接触 到 Windows
使用 Invoke/BeginInvoke/InvokeAsync 的代码不会出问题 Application.DoShutdown 方法被 ShutdownImpl 包装,且所有调用均从此包装进入,因此...立即关闭 CriticalInvokeShutdown,即以 Send 优先级 Invoke 关闭方法,而 Send 优先级调用 Invoke 几乎等同于直接调用(为什么是等同而不是直接调用?...} 由于此终止代码在 Dispatcher 所在的线程执行,而所有 Invoke/BeginInvoke/InvokeAsync 代码也都在此线程执行,因此这些代码均不会并发。...已经执行的代码会在此终止代码之前,而在此终止代码之后也不会再执行任何 Invoke/BeginInvoke/InvokeAsync 的任务了。...所有通过 Invoke/BeginInvoke/InvokeAsync 或间接通过此方法(如 WPF 控件相关事件)调用的代码,均不会遭遇 Application.Current 为 null。
领取专属 10元无门槛券
手把手带您无忧上云