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 = "按下按钮";
			 }
};
}



相关文章推荐

C#委托主线程调用控件并且同步UI界面显示以及协议制作

using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; usin...

在C++中实现委托(Delegate)

原文地址 个人理解: 说明: 最近在阅读设计模式相关的内容, 正好看到观察者模式的部分, 发现.net 有一个委托机制, 本质上就是函数指针对象。 这篇大作中...

Delphi7高级应用开发随书源码

  • 2003年04月30日 00:00
  • 676KB
  • 下载

[置顶] 在C#中使用SerialPort类实现串口通信(陆续更新)

[置顶] 在C#中使用SerialPort类实现串口通信(陆续更新) 标签: c#newlineobjectbytestringstream 2009-08-23 13:16 8523...

VC++ .NET 动态加载DLL,使用反射方式Invoke委托调用

每次新产品都需要配一个上位机,并且本地配置与远程配置都需要重新开放配置程序,因此就想办法把配置模块变为一个动态的控件,一次开发后续2个程序都可以同时使用,使用了很多种方法,最后还是使用反射方式. ...
  • cp1300
  • cp1300
  • 2015年10月09日 21:50
  • 1057

VC++调用webservice (不使用.NET的托管技术)

正在看着AV(AreCont)SDK的时候,老大突然让我转到soap上,原因是刚进公司的我,第一项任务便是研究ONVIF(so many specifications),当然主要的还是看core ...

vs2005 vc++ 生成非托管的 不需要.net运行环境的exe程序方法

在VS2005里开发的VC++程序在编译的时候,微软默认会加入自己的 .Net Framework (方便推广自家产品),让你的VC++程序依赖它,这就导致程序编译后,无法跟往常一样直接打包,在别的机...

.Net调用非托管代码(P/Invoke与C++InterOP)

1 .Net互操作 .Net不能直接操作非托管代码,这时就需要互操作了。 1.1 P/Invoke 许多常用Windows操作都有托管接口,但是还有许多完整的 Win32 部分没有托管接口。如何...

c#Winform异步线程刷新UI

  • 2015年12月27日 10:25
  • 50KB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:VC++ .NET UI同步(使用Invoke托管方法),异步线程调用UI
举报原因:
原因补充:

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