VC++ .NET UI同步(使用Invoke托管方法),异步线程调用UI

原创 2015年01月28日 22:04:23

花了好几天才学会,之前的代码都是C#的,无法直接使用.


1.首先定义并声明托管

delegate void testUI1(String ^ptr);	//定义一个UI托管
		delegate void testUI2(String ^ptr);	//定义一个UI托管
		testUI1^ myUI1;
		testUI2^ myUI2;

2.在构造函数中实例化托管对象

myUI1 = gcnew testUI1( this, &test::Form1::UI_Test1);
myUI2 = gcnew testUI2( this, &test::Form1::UI_Test2);

3.托管中调用的函数(主要用于UI操作)

void UI_Test1(String ^ptr)  //这个是被线程调用的函数
{
label1->Text=ptr;
}

void UI_Test2(String ^ptr)  //这个是被线程调用的函数
{
label2->Text=ptr;
}

4.在异步线程中使用托管访问UI

		//线程1
		void TestThread(void)
		{
			DWORD i=0;

			//防止在窗口句柄初始化之前就走到下面的代码
			while (!this->IsHandleCreated)
			{
				Sleep(10);
			}

			//Sleep(1000);	//一定要延时之后再建立线程,否则会出现
			//在创建窗口句柄之前,不能在控件上调用 Invoke 或 BeginInvoke
			//主要是因为UI界面还没有初始化完成,调用Invoke会出错
			while(1)
			{
				this->Invoke(myUI1, ""+i);
				i ++;
				Sleep(1000);
			}
		}


		//线程2
		void TestThread1(void)
		{
			DWORD i=1000;

			//防止在窗口句柄初始化之前就走到下面的代码
			while (!this->IsHandleCreated)
			{
				Sleep(10);
			}

			//Sleep(2000);	//一定要延时之后再建立线程,否则会出现
			//在创建窗口句柄之前,不能在控件上调用 Invoke 或 BeginInvoke
			//主要是因为UI界面还没有初始化完成,调用Invoke会出错
			while(1)
			{
				this->Invoke(myUI2, ""+i);
				i ++;
				Sleep(1000);
			}
		}




运行效果




附上所有代码

#pragma once

#include "stdafx.h"
#include "windows.h"


#pragma comment(lib, "advapi32.lib")
#pragma comment(lib, "Ws2_32.lib")  
#pragma comment(lib, "User32.lib") 

namespace test {

	using namespace System;
	using namespace System::ComponentModel;
	using namespace System::Collections;
	using namespace System::Windows::Forms;
	using namespace System::Data;
	using namespace System::Drawing;
	using namespace System::Threading;

	/// <summary>
	/// Form1 摘要
	/// </summary>
	public ref class Form1 : public System::Windows::Forms::Form
	{

		System::Threading::Thread  ^Thread1;
		System::Threading::Thread  ^Thread2;

		delegate void testUI1(String ^ptr);	//定义一个UI托管
		delegate void testUI2(String ^ptr);	//定义一个UI托管
		testUI1^ myUI1;
		testUI2^ myUI2;

	public:
		Form1(void)
		{

			InitializeComponent();


			myUI1 = gcnew testUI1( this, &test::Form1::UI_Test1);
			myUI2 = gcnew testUI2( this, &test::Form1::UI_Test2);

			

			this->Thread1 = gcnew Thread (gcnew ThreadStart (this,&test::Form1::TestThread));
			this->Thread1->Start();
			this->Thread1->IsBackground = TRUE;	//将读取线程设置为后台线程,这样在UI线程关闭后可以自动退出
			this->Thread2 = gcnew Thread (gcnew ThreadStart (this,&test::Form1::TestThread1));
			this->Thread2->Start();
			this->Thread2->IsBackground = TRUE;	//将读取线程设置为后台线程,这样在UI线程关闭后可以自动退出
			//
			//TODO: 在此处添加构造函数代码
			//

			this->label1->Text="";
			this->label2->Text="";
		}

		void UI_Test1(String ^ptr)  //这个是被线程调用的函数
		{
			this->label1->Text=ptr;
		}

		void UI_Test2(String ^ptr)  //这个是被线程调用的函数
		{
			this->label2->Text=ptr;
		}

		//线程1
		void TestThread(void)
		{
			DWORD i=0;

			//防止在窗口句柄初始化之前就走到下面的代码
			while (!this->IsHandleCreated)
			{
				Sleep(10);
			}

			//Sleep(1000);	//一定要延时之后再建立线程,否则会出现
			//在创建窗口句柄之前,不能在控件上调用 Invoke 或 BeginInvoke
			//主要是因为UI界面还没有初始化完成,调用Invoke会出错
			while(1)
			{
				this->Invoke(myUI1, ""+i);
				i ++;
				Sleep(1000);
			}
		}


		//线程2
		void TestThread1(void)
		{
			DWORD i=1000;

			//防止在窗口句柄初始化之前就走到下面的代码
			while (!this->IsHandleCreated)
			{
				Sleep(10);
			}

			//Sleep(2000);	//一定要延时之后再建立线程,否则会出现
			//在创建窗口句柄之前,不能在控件上调用 Invoke 或 BeginInvoke
			//主要是因为UI界面还没有初始化完成,调用Invoke会出错
			while(1)
			{
				this->Invoke(myUI2, ""+i);
				i ++;
				Sleep(1000);
			}
		}

	protected:
		/// <summary>
		/// 清理所有正在使用的资源。
		/// </summary>
		~Form1()
		{
			if (components)
			{
				delete components;
			}
		}
	private: System::Windows::Forms::Label^  label1;
	protected: 
	private: System::Windows::Forms::Label^  label2;
	private: System::Windows::Forms::Button^  button1;

	private:
		/// <summary>
		/// 必需的设计器变量。
		/// </summary>
		System::ComponentModel::Container ^components;

#pragma region Windows Form Designer generated code
		/// <summary>
		/// 设计器支持所需的方法 - 不要
		/// 使用代码编辑器修改此方法的内容。
		/// </summary>
		void InitializeComponent(void)
		{
			this->label1 = (gcnew System::Windows::Forms::Label());
			this->label2 = (gcnew System::Windows::Forms::Label());
			this->button1 = (gcnew System::Windows::Forms::Button());
			this->SuspendLayout();
			// 
			// label1
			// 
			this->label1->AutoSize = true;
			this->label1->Font = (gcnew System::Drawing::Font(L"宋体", 20, System::Drawing::FontStyle::Regular, System::Drawing::GraphicsUnit::Point, 
				static_cast<System::Byte>(134)));
			this->label1->ForeColor = System::Drawing::Color::FromArgb(static_cast<System::Int32>(static_cast<System::Byte>(0)), static_cast<System::Int32>(static_cast<System::Byte>(0)), 
				static_cast<System::Int32>(static_cast<System::Byte>(192)));
			this->label1->Location = System::Drawing::Point(106, 64);
			this->label1->Name = L"label1";
			this->label1->Size = System::Drawing::Size(96, 27);
			this->label1->TabIndex = 0;
			this->label1->Text = L"label1";
			// 
			// label2
			// 
			this->label2->AutoSize = true;
			this->label2->Font = (gcnew System::Drawing::Font(L"宋体", 20, System::Drawing::FontStyle::Regular, System::Drawing::GraphicsUnit::Point, 
				static_cast<System::Byte>(134)));
			this->label2->ForeColor = System::Drawing::Color::Red;
			this->label2->Location = System::Drawing::Point(109, 139);
			this->label2->Name = L"label2";
			this->label2->Size = System::Drawing::Size(96, 27);
			this->label2->TabIndex = 1;
			this->label2->Text = L"label2";
			// 
			// button1
			// 
			this->button1->Location = System::Drawing::Point(216, 226);
			this->button1->Name = L"button1";
			this->button1->Size = System::Drawing::Size(75, 23);
			this->button1->TabIndex = 2;
			this->button1->Text = L"button1";
			this->button1->UseVisualStyleBackColor = true;
			this->button1->Click += gcnew System::EventHandler(this, &Form1::button1_Click);
			// 
			// Form1
			// 
			this->AutoScaleDimensions = System::Drawing::SizeF(6, 12);
			this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;
			this->ClientSize = System::Drawing::Size(503, 288);
			this->Controls->Add(this->button1);
			this->Controls->Add(this->label2);
			this->Controls->Add(this->label1);
			this->Name = L"Form1";
			this->Text = L"Form1";
			this->Load += gcnew System::EventHandler(this, &Form1::Form1_Load);
			this->ResumeLayout(false);
			this->PerformLayout();

		}
#pragma endregion
	private: System::Void Form1_Load(System::Object^  sender, System::EventArgs^  e) {
			 }
	private: System::Void button1_Click(System::Object^  sender, System::EventArgs^  e) {
				 this->label1->Text = "按下按钮";
				 this->label2->Text = "按下按钮";
			 }
};
}



多线程中InvokeRequired和Invoke的用法,讲的很清楚

C#中禁止跨线程直接访问控件,InvokeRequired是为了解决这个问题而产生的,当一个控件的InvokeRequired属性值为真时,说明有一个创建它以外的线程想访问它。此时它将会在内部调用ne...
  • mycomputerxiaomei
  • mycomputerxiaomei
  • 2014年10月14日 10:40
  • 1887

C# 多线程 用委托实现异步_调用委托的BeginInvoke和EndInvoke方法

1.C#中的每一个委托都内置了BeginInvoke和EndInvoke方法,如果委托的方法列表里只有一个方法,那么这个方法就可以异步执行(不在当前线程里执行,另开辟一个线程执行)。委托的BeginI...
  • xuanwuziyou
  • xuanwuziyou
  • 2014年12月04日 15:38
  • 4831

为什么我们可以在非UI线程中更新UI

尊重原创转载请注明:From AigeStudio(http://blog.csdn.net/aigestudio)Power by Aige 侵权必究! 炮兵镇楼 看到这样的标题……估计...
  • sun20209527
  • sun20209527
  • 2015年11月05日 15:50
  • 1164

c#多线程与异步开发 (上)

项目中需要一些多线程或异步的知识点,找资料时看到了这篇文章,觉得讲的很不错,转载过来,想要学习的可以看原文,原文链接,感谢原作者提供好文章引言本文主要从线程的基础用法,CLR线程池当中工作者线程与I/...
  • suifcd
  • suifcd
  • 2016年01月22日 19:32
  • 4690

C#线程之异步调用(一)执行长时间的方法

转自:http://www.oecp.cn/hi/LiuBP/blog/2262
  • Baple
  • Baple
  • 2014年04月19日 15:03
  • 4521

android 异步回调中操作UI线程,UI同步、卡死阻塞等性能问题

android开发中,回调无处不在,整个android开发的框架就是以回调机制建立起来的。如:activity,service,broadcast,fragment,view事件监听,baseadap...
  • lxlmycsdnfree
  • lxlmycsdnfree
  • 2017年04月10日 18:48
  • 506

C# 用委托BeginInvoke做异步线程

一个应用场景,浏览器上传一个文件,此文件后台调用文件转换,需要耗费相当长的时间,这样,如果是一个线程同步式的做下去,那么用户在浏览器上感觉就是卡住了,卡卡卡卡,这里我们利用委托的BeginInvoke...
  • chenqiangdage
  • chenqiangdage
  • 2015年11月18日 17:48
  • 2199

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

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

c#利用委托跨线程调用UI控件完整使用方法

在子线程中通过委托访问form并修改UI控件
  • tonggen7135
  • tonggen7135
  • 2017年12月08日 09:51
  • 109

C#子线程更新UI控件的方法实例总结

本文实例总结了C#子线程更新UI控件的方法,对于桌面应用程序设计的UI界面控制来说非常有实用价值。分享给大家供大家参考之用。具体分析如下: 一般在winform C/S程序中经常会在子线程中更新控件...
  • rattles
  • rattles
  • 2016年06月27日 20:34
  • 1302
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:VC++ .NET UI同步(使用Invoke托管方法),异步线程调用UI
举报原因:
原因补充:

(最多只允许输入30个字)