【win32多线程】数据的一致性问题,即多个线程读写数据问题

Windows进程间通信 - 使用共享文件与内存 一、共享内存原理 在32位的系统中,每一个进程都有4G连续的虚拟内存,且每一个进程这4G的虚拟内存块是互不共享。而为达到每个进程能够操作同一块内存,Window提供了内存映射文件的方式,简单的说每一个进程的一段虚拟内存对应于同一个文件或类文件的资源,使得每个进程能够操作同一个文件会类文件资源,从而达到内存共享的效果。 知识点: (1)为什么是4G? 32位系统寻址 2^32 = 4G (... 阅读详情

1.把锁定搬到更高的层次

void AddLineItems(List *pList)
{
Node node;
while()
{
getLineItem(&item);
AddHead(pList,&node);
}
}


void AddHead(List *pList,Node *pNode)
{
EnterCriticalSection(&pList->critical_sec);
pNode->next=pList->head;
pList->head=pNode;
LeaveCriticalSection(&pList->critical_sec);
}

搬到更高的层次

void AddLineItems(List *pList)
{
Node node;
EnterCriticalSection(&pList->critical_sec);
while()
{
getLineItem(&item);
AddHead(pList,&node);
}
LeaveCriticalSection(&pList->critical_sec);
}

void AddHead(List *pList,Node *pNode)
{
pNode->next=pList->head;
pList->head=pNode;
}

这样的模型有助于windows程序,因为其线程是事件驱动模式,而且常常返回到主消息循环中。


2.读写锁
排他锁看起来不错,但是它会强迫所有的存取操作都按照先后次序来,而多线程的好处也就流失了。这种情况下最好用单一线程。

为Reader锁定
Lock(ReaderMutex)
ReadCount=ReadCount+1;
if(ReadCount==0)
   Unlock(DataSemaphore)
Unlock(ReaderMutex)

为Reader解除锁定
Lock(ReaderMutex)
ReadCount=ReadCount-1;
if(ReadCount==0)
   Unlock(DataSemaphore)
Unlock(ReaderMutex)

为Writer锁定
Lock(DataSemaphore)

为Writer解除锁定
Unlock(DataSemaphore)


实现Reader/Writer的数据结构

ReadWrit.h

typedef struct _RWLock
{
    // Handle to a mutex that allows
    // a single reader at a time access
    // to the reader counter.
    HANDLE	hMutex;

    // Handle to a semaphore that keeps
    // the data locked for either the
    // readers or the writers.
    HANDLE	hDataLock;

    // The count of the number of readers.
    // Can legally be zero or one while
    // a writer has the data locked.
	int		nReaderCount;
} RWLock;

//
// Reader/Writer prototypes
//

BOOL InitRWLock(RWLock *pLock);
BOOL DestroyRWLock(RWLock *pLock);
BOOL AcquireReadLock(RWLock *pLock);
int ReleaseReadLock(RWLock *pLock);
BOOL AcquireWriteLock(RWLock *pLock);
int ReleaseWriteLock(RWLock *pLock);
BOOL ReadOK(RWLock *pLock);
BOOL WriteOK(RWLock *pLock);

BOOL FatalError(char *s);


读者与写者算法:

#define WIN32_LEAN_AND_MEAN
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include "ReadWrit.h"

// If we wait more than 2 seconds, then something is probably wrong!
#define MAXIMUM_TIMEOUT 2000

// Here's the pseudocode for what is going on:
//
// Lock for Reader:
//  Lock the mutex
//  Bump the count of readers
//  If this is the first reader, lock the data
//  Release the mutex
//
// Unlock for Reader:
//  Lock the mutex
//  Decrement the count of readers
//  If this is the last reader, unlock the data
//  Release the mutex
//
// Lock for Writer:
//  Lock the data
//
// Unlock for Reader:
//  Unlock the data

///////////////////////////////////////////////////////

BOOL MyWaitForSingleObject(HANDLE hObject)
{
    DWORD result;

    result = WaitForSingleObject(hObject, MAXIMUM_TIMEOUT);
    // Comment this out if you want this to be non-fatal
    if (result != WAIT_OBJECT_0)
        FatalError("MyWaitForSingleObject - Wait failed, you probably forgot to call release!");
    return (result == WAIT_OBJECT_0);
}

BOOL InitRWLock(RWLock *pLock)
{
    pLock->nReaderCount = 0;
    pLock->hDataLock = CreateSemaphore(NULL, 1, 1, NULL);
    if (pLock->hDataLock == NULL)
        return FALSE;
    pLock->hMutex = CreateMutex(NULL, FALSE, NULL);
    if (pLock->hMutex == NULL)
    {
        CloseHandle(pLock->hDataLock);
        return FALSE;
    }
    return TRUE;
}

BOOL DestroyRWLock(RWLock *pLock)
{
    DWORD result = WaitForSingleObject(pLock->hDataLock, 0);
    if (result == WAIT_TIMEOUT)
        return FatalError("DestroyRWLock - Can't destroy object, it's locked!");

    CloseHandle(pLock->hMutex);
    CloseHandle(pLock->hDataLock);
    return TRUE;
}

BOOL AcquireReadLock(RWLock *pLock)
{
    BOOL result = TRUE;

    if (!MyWaitForSingleObject(pLock->hMutex))
        return FALSE;
 
    if(++pLock->nReaderCount == 1)
        result = MyWaitForSingleObject(pLock->hDataLock);

    ReleaseMutex(pLock->hMutex);
    return result;
}

BOOL ReleaseReadLock(RWLock *pLock)
{
    int result;
    LONG lPrevCount;

    if (!MyWaitForSingleObject(pLock->hMutex))
        return FALSE;

    if (--pLock->nReaderCount == 0)
        result = ReleaseSemaphore(pLock->hDataLock, 1, &lPrevCount);

    ReleaseMutex(pLock->hMutex);
    return result;
}

BOOL AcquireWriteLock(RWLock *pLock)
{
    return MyWaitForSingleObject(pLock->hDataLock);
}

BOOL ReleaseWriteLock(RWLock *pLock)
{
    int result;
    LONG lPrevCount;

    result = ReleaseSemaphore(pLock->hDataLock, 1, &lPrevCount);
    if (lPrevCount != 0)
        FatalError("ReleaseWriteLock - Semaphore was not locked!");
    return result;
}

BOOL ReadOK(RWLock *pLock)
{
    // This check is not perfect, because we
    // do not know for sure if we are one of
    // the readers.
    return (pLock->nReaderCount > 0);
}

BOOL WriteOK(RWLock *pLock)
{
    DWORD result;

    // The first reader may be waiting in the mutex,
    // but any more than that is an error.
    if (pLock->nReaderCount > 1)
        return FALSE;

    // This check is not perfect, because we
    // do not know for sure if this thread was
    // the one that had the semaphore locked.
    result = WaitForSingleObject(pLock->hDataLock, 0);
    if (result == WAIT_TIMEOUT)
        return TRUE;

    // a count is kept, which was incremented in Wait.
    result = ReleaseSemaphore(pLock->hDataLock, 1, NULL);
    if (result == FALSE)
        FatalError("WriteOK - ReleaseSemaphore failed");
    return FALSE;
}

///////////////////////////////////////////////////////

/*
 * Error handler
 */
BOOL FatalError(char *s)
{
    fprintf(stdout, "%s\n", s);
    // Comment out exit() to prevent termination
    exit(EXIT_FAILURE);
    return FALSE;
}


主文件,多读者和写者对链表的操作

#define WIN32_LEAN_AND_MEAN
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include "ReadWrit.h"

///////////////////////////////////////////////////////

//
// Structure definition
//

typedef struct _Node
{
    struct _Node *pNext;
    char	szBuffer[80];
} Node;

typedef struct _List
{
	RWLock	lock;
    Node	*pHead;
} List;

//
// Linked list prototypes
//

BOOL InitRWLock(RWLock *pLock);
BOOL DeleteList(List *pList);
BOOL AddHead(List *pList, Node *node);
BOOL DeleteHead(List *pList);
BOOL Insert(List *pList, Node *afterNode, Node *newNode);
Node *Next(List *pList, Node *node);

//
// Test functions prototypes
//

DWORD WINAPI LoadThreadFunc(LPVOID n);
DWORD WINAPI SearchThreadFunc(LPVOID n);
DWORD WINAPI DeleteThreadFunc(LPVOID n);

//
// Global variables
//

// This is the list we use for testing
List *gpList;

///////////////////////////////////////////////////////

List *CreateList()
{
    List *pList = GlobalAlloc(GPTR, sizeof(List));
	if (InitRWLock(&pList->lock) == FALSE)
	{
		GlobalFree(pList);
		pList = NULL;
	}
    return pList;
}

BOOL DeleteList(List *pList)
{
	AcquireWriteLock(&pList->lock);
	while (DeleteHead(pList))
		;
	ReleaseWriteLock(&pList->lock);

	DestroyRWLock(&gpList->lock);

    GlobalFree(pList);

	return TRUE;
}

BOOL AddHead(List *pList, Node *pNode)
{
	if (!WriteOK(&pList->lock))
		return FatalError("AddHead - not allowed to write!");

    pNode->pNext = pList->pHead;
    pList->pHead = pNode;
}

BOOL DeleteHead(List *pList)
{
	Node *pNode;

	if (!WriteOK(&pList->lock))
		return FatalError("AddHead - not allowed to write!");

	if (pList->pHead == NULL)
		return FALSE;

	pNode = pList->pHead->pNext;
	GlobalFree(pList->pHead);
    pList->pHead = pNode;
	return TRUE;
}

BOOL Insert(List *pList, Node *afterNode, Node *newNode)
{
	if (!WriteOK(&pList->lock))
		return FatalError("Insert - not allowed to write!");

    if (afterNode == NULL)
    {
        AddHead(pList, newNode);
    }
    else
    {
        newNode->pNext = afterNode->pNext;
        afterNode->pNext = newNode;
    }
}

Node *Next(List *pList, Node *pNode)
{
	if (!ReadOK(&pList->lock))
	{
		FatalError("Next - Not allowed to read!");
		return NULL;
	}

	if (pNode == NULL)
		return pList->pHead;
	else
	    return pNode->pNext;
}

///////////////////////////////////////////////////////

DWORD WINAPI ThreadFunc(LPVOID);

int main()
{
    HANDLE  hThrds[4];
    int     slot = 0;
	int		rc;
	int		nThreadCount = 0;
    DWORD	dwThreadId;

	gpList = CreateList();
	if (!gpList)
		FatalError("main - List creation failed!");

    hThrds[nThreadCount++] = CreateThread(NULL,
        0, LoadThreadFunc, 0, 0, &dwThreadId );

    hThrds[nThreadCount++] = CreateThread(NULL,
        0, SearchThreadFunc, (LPVOID)"pNode", 0, &dwThreadId );

    hThrds[nThreadCount++] = CreateThread(NULL,
        0, SearchThreadFunc, (LPVOID)"pList", 0, &dwThreadId );

    hThrds[nThreadCount++] = CreateThread(NULL,
        0, DeleteThreadFunc, 0, 0, &dwThreadId );

    /* Now wait for all threads to terminate */
    rc = WaitForMultipleObjects(
        nThreadCount,
        hThrds,
        TRUE,
        INFINITE );

    for (slot=0; slot<nThreadCount; slot++)
        CloseHandle(hThrds[slot]);
    printf("\nProgram finished.\n");

	DeleteList(gpList);

    return EXIT_SUCCESS;
}

/*
 * Slowly load the contents of "List.c" into the
 * linked list.
 */
DWORD WINAPI LoadThreadFunc(LPVOID n)
{
	int nBatchCount;
	Node *pNode;

	FILE* fp = fopen("List.c", "r");
	if (!fp)
	{
		fprintf(stderr, "ReadWrit.c not found\n");
		exit(EXIT_FAILURE);
	}

	pNode = GlobalAlloc(GPTR, sizeof(Node));
	nBatchCount = (rand() % 10) + 2;
	AcquireWriteLock(&gpList->lock);

	while (fgets(pNode->szBuffer, sizeof(Node), fp))
	{
		AddHead(gpList, pNode);

		// Try not to hog the lock
		if (--nBatchCount == 0)
		{
			ReleaseWriteLock(&gpList->lock);
			Sleep(rand() % 5);
			nBatchCount = (rand() % 10) + 2;
			AcquireWriteLock(&gpList->lock);
		}
		pNode = GlobalAlloc(GPTR, sizeof(Node));
	}

	ReleaseWriteLock(&gpList->lock);
	return 0;
}


/*
 * Every so often, walked the linked list
 * and figure out how many lines one string
 * appears (given as the startup param)
 */
DWORD WINAPI SearchThreadFunc(LPVOID n)
{
	int i;
	char *szSearch = (char *)n;

	for (i=0; i<20; i++)
	{
		int		nFoundCount = 0;
		Node   *next = NULL;

		AcquireReadLock(&gpList->lock);
		next = Next(gpList, next);
		while (next)
		{
			if (strstr(next->szBuffer, szSearch))
				nFoundCount++;
			next = Next(gpList, next);
		}

		ReleaseReadLock(&gpList->lock);

		printf("Found %d lines with '%s'\n", nFoundCount, szSearch);
		Sleep((rand() % 30));
	}
    return 0;
}


/*
 * Every so often, delete some entries in the list.
 */
DWORD WINAPI DeleteThreadFunc(LPVOID n)
{
	int i;

	for (i=0; i<100; i++)
	{
		Sleep(1);
		AcquireWriteLock(&gpList->lock);
		DeleteHead(gpList);
		DeleteHead(gpList);
		DeleteHead(gpList);
		ReleaseWriteLock(&gpList->lock);
	}

    return 0;
}


 

win32串口读写多线程同步 在Win32下进行串口的操作时,会用到CreateFile、ReadFile、Writefile等几个函数,其中涉及串口的同步模式和异步模式, 在单线程时使用同步模式和异步模式没有太大的关系,都可以很好的使用。但是在多线程中进行读写就需要考虑串口资源的 同步问题了,以为windows下串口资源同时只能被一个线程占用,读写同时进行会导致程序锁死,因此可以使用信号量进行同步控制。 例如,封装之后 阅读详情

相关推荐

[Win32] 多线程和线程同步

多线程:一个进程创建时,默认情况下系统会为它创建一个主线程,(如果使用Native API创建的线程就没有主线程,是空的,必须自己创建主线程),应用程序可以自己创建线程,还有以前写过的一篇“DLL注入技术”,就是远程在其他进程中创建线程,然后让远程线程load我们的dll。 系统是如何实现多线程的?其实,对于单CPU单核心的设备上,在一个确定的时刻,只能执行内存中的一个指令。所谓的“多任务抢占式

zuishikonghuan的博客 6266

windows多线程之读写同步(线程锁Mutex + 信号量Semaphore )

Windows读写线程问题记录

w15131277180的博客 955

C++ 多线程(三) Win32多线程2

C++ 多线程(三) Win32多线程2 同步/资源共享 线程之间的同步 在下面的例子中,两个线程用于计算给定范围内的所有质数。 它演示了一个数字是否为质数的测试: #include <Windows.h> #include <process.h> #include <stdio.h> #include <math.h> volatile int counter = 0; int isPrime(int n) { for(int i = 2; i

jianbiancheng的博客 561

DataLoader windows平台下 多线程读数据报错 | BrokenPipeError: [Errno 32] Broken pipe | freeze_support()

DataLoader多线程读取数据 使用DataLoader读取数据时,为了加快效率,所以使用了多个线程,即num_workers不为0,在windows下报了错误。 DataLoader(trainset, batch_size=128, shuffle=True, num_workers=2) https://github.com/pytorch/pytorch/pull/5585...

Jemary_的博客 5000

Win32 API下的多线程程序设计实战

本文还有配套的精品资源,点击获取 简介:本文深入探讨了如何使用Win32 API在Windows平台实现多线程编程,涵盖了多线程概念、线程创建、线程同步、线程通信和线程生命周期管理。实例程序通过创建多个线程来执行不同功能,如用户界面更新、计算、数据加载和定时器任务,以提升应用程序的性能和响应性。 1. 多线程概念及其重要性 多线程编程是现代操作系统中提高程序...

weixin_29607511的博客 1142

Win32 API下C语言多线程编程示例

多线程(Multithreading)是指在同一个程序内同时运行多个线程执行不同的任务,以达到提高程序运行效率和响应速度的目的。每个线程可以看作是独立的执行路径,能够在同一进程的上下文中共享资源和数据。Windows操作系统通过提供一组丰富的API来管理线程,即Windows API(Application Programming Interface),通常被称为Win32 API。Win32 API允许开发者创建、管理和终止线程,同时提供了控制线程同步和通信的功能。

weixin_42575109的博客 889

Win32多线程同步方法

因为最近要做多线程方面的工作, 用到多线程的内容, 而网上搜了不少都是一些没什么用, 零零散散的内容, 根本没有系统和可学性. 看了>对于在windows32平台上的多线程编程, 有很好的指导作用.        下面先说一下线程同步的几种方法:(如果看不懂下面术语的话,先看一些基本书籍, 最好看看MSDN)         1. Interlocked系列函数: 是一系列原子操作. 如果

行者无疆的专栏 1776

Win32多线程程序设计指南与实践

本文还有配套的精品资源,点击获取 简介:Windows环境下的多线程编程技术能够有效提高CPU资源利用率,实现程序的高并发执行。本书详细介绍了多线程编程的核心概念、线程的创建与管理、同步机制、通信方式、线程优先级调整、局部存储、终止和性能优化等方面的知识。书中还探讨了调试多线程程序的技巧,并通过实例和实践指导,帮助开发者掌握在Win32平台上构建高效、稳定并发程序的能力。 ...

weixin_36474001的博客 1392

Windows多线程问题

进程和线程是操作系统里面经常遇到的两个概念,还有一个概念,是应用程序。应用程序包括指令和数据,在开始运行之前,只是分布在磁盘上的指令和数据。正在执行的应用程序称为进程,进程不仅仅是指令和数据,它还有状态。状态是保存在处理器寄存器中的一些值,记录一些信息,比如说当前执行指令的地址,保存在内存中的值等。进程是应用程序的基本构件块,同时运行的多个应用程序就是多个进程。每个进程可以运行多个线程。线程也有一

面目全非,胸有丘壑 | Json Lee 3905

Win32多线程程序设计:深入理解与源码改进

在现代操作系统中,多线程编程是一种普遍的现象,它允许程序在多核心处理器上并行执行多个任务,提升应用程序的响应性和效率。Win32 API是Windows操作系统的核心应用程序接口,它提供了一系列函数和数据结构,使得开发者可以方便地在Windows平台上实现多线程程序设计。

weixin_26805451的博客 1074

5分钟快速搭建:使用ros1_bridge实现ROS2容器与ROS1主机的无缝通信

本文详细介绍了如何在5分钟内快速搭建基于ros1_bridge的通信方案,实现运行在Docker容器中的ROS2节点与宿主机ROS1系统的无缝数据交换。通过环境隔离、Docker容器化部署及选择性桥接配置,该方案能有效整合新旧系统,避免大规模代码重构,是机器人项目渐进式升级的实用策略。

weixin_29268637的博客 178

Win32多线程处理技术【线程的创建】

线程的创建 线程内核对象 线程的终止 线程的优先级 Windows程序的执行单元 多线程 进程---主线程---辅助线程 主线程在运行过程中还可以创建新的线程,即多线程。在同一进程中运行不同的线程的好处是这些线程可以共享进程的资源,如全局变量,句柄等。各个线程也可以用自己私有的堆栈用于保存私有数据。 线程的创建 线程描述了进程内代码的执行路径。进程内可以有多个线程来执行,为了使他...

平凡 1641

基于AXI PCIE IP的FPGA PCIE卡示意图

如果在上图中的AXI互联IP上再连接一个带AXI Slave接口的BRAM控制器,这个BRAM控制器连接一个BRAM,Host PC在系统主存中分配了一些不连续的内存,Host PC可以将这些内存段的起始地址(当然要先转为PCIE总线地址)写到AXI总线上的BRAM中,这样AXI CDMA读取BRAM,将读取到的PCIE总线基地址写到AXIPCIE寄存器块中的AXIBAR2PCIEBAR_n寄存器中,这样就实现了SG DMA。通过动态改变AXIBAR2PCIEBAR_n寄存器的值,可以实现多通道DMA。

csdn_gddf102384398的博客 1623

Win32API下的多线程编程入门

多线程,Multi-Thread。移步别处理解Thread和Process。多线程可用多种API实现,这里用Win32 API实现最简单的多线程,线程彼此独立,不涉及线程间的数据共享。 先直接上程序:

一只飞鸟的自白 2884

晶圆表面缺陷检测现状概述

凹坑,凸起,尖角,沟槽),使用光束对晶圆进行照射,收集反射光和散射光信息进行缺陷判断,进一步可分为无图案晶圆表面检测和宏观缺陷检测设备。KLA使用SR-DUV光,检测精度在10nm以下。扫描电子显微(电子束和晶圆表面产生二次电子,X射线等)获取高分辨率的图像,然后用图像处理表面缺陷(凹坑,凸起,尖角,沟槽等)表面容貌和材料信息,分辨率可达5-10nm。晶圆表面缺陷检测设备主要检测晶圆外观呈现出来的缺陷,损伤、毛刺等缺陷,主要设备供应商KLA,AMAT,日立等,其中KLA在晶圆表面检测设备占有市场52%左右。

qq_36786800的博客 1万+

新手必看:如何用Python模拟电动助力转向系统(EPS)的传感器信号处理

本文详细介绍了如何使用Python模拟电动助力转向系统(EPS)的传感器信号处理流程,包括转向力矩、转向角度和车速信号的生成与滤波处理。通过实战代码示例,帮助开发者理解ECU如何计算助力扭矩,并提供了可视化分析和性能优化建议,适合汽车电子系统开发新手学习。

weixin_28327051的博客 354

win32多线程编程

一、问题的提出 编写一个耗时的单线程程序:   新建一个基于对话框的应用程序SingleThread,在主对话框IDD_SINGLETHREAD_DIALOG添加一个按钮,ID为IDC_SLEEP_SIX_SECOND,标题为“延时6秒”,添加按钮的响应函数,代码如下:  void CSingleThreadDlg::OnSleepSixSecond()  {  Sleep(

579

应用软件——Altium Designer 19 Gerber/坐标文件

如何输出Gerber文件 步骤如下: 打开需要输出的PCB文件 2. 设置原点坐标 3. 打开Gerber Files 选项,File–>Fabrication Opuputs–>Gerber Files。 4. General参数设置。 用于指定输出Gerber文件中使用的单位(Units)和格式(Format)。单位可以是公制(Millimeters)和英制(Inches);格式栏中2:3,2:4,2:5代表文件中使用的不同数据精度,其中2:3表示数据含2位整数3位小数;相应的,另外两个分

染血黑兔的博客 7202

MFC多线程各种线程用法

一、问题的提出    编写一个耗时的单线程程序:      新建一个基于对话框的应用程序SingleThread,在主对话框IDD_SINGLETHREAD_DIALOG添加一个按钮,ID为 IDC_SLEEP_SIX_SECOND,标题为“延时6秒”,添加按钮的响应函数,代码如下:     void CSingleThreadDlg::OnSleepSixSecond()     {    Sl...

徐丨若木 2万+

【NodeRed】node-red-contrib-opcua实现PLC读写

在之前的博文【Node-RED】node-red-contrib-opcua-server模块使用(1)中,我们介绍了用node-red-contrib-opcua-server模块实现OPCUA服务端的,以及二次开发的内容。本节博文中我们采用官方社区自带的node-red-contrib-opcua组件开展对OPCUA客户端的介绍,详细阐述用该组件中OpcUa-Client节点实现客户端对PLC的读写,以及实现过程中遇到的问题。由于官方社区中并没有找到该组件的介绍实例,这也是本博文编写的第1个原因。

weixin_48618536的博客 957

【AutoCAD中实现双击文本编辑功能】

例如:以下是官方博客例子浅析先加入相关的头文件和库文件。在AutoCAD中有一个很重要的功能,就是双击图形尺寸或文本后会出现一个文本编辑框,用户可在该编辑框中修改文字。本文介绍了如何使用AcEdInplaceTextEditor来实现该功能。实现cad的消息监听。创建一个消息监听的类并在cad中注册来实现消息监听。主要是监听键盘输入。提示:以下是本篇文章正文内容,下面案例可供参考提示:这里对文章进行总结:例如:以上就是今天要讲的内容,本文仅仅简单介绍了的函数和方法。

我的博客 1148

Win32 多线程

Win32 API是Windows操作系统内核与应用程序之间的界面,它将内核提供的功能进行函数包装,应用程序通过调用相关函数而获得相应的系统功能。为了向应用程序提供多线程功能,Win32 API函数集中提供了一些处理多线程程序的函数集。直接用Win32 API进行程序设计具有很多优点: 基于Win32的应用程序执行代码小,运行效率高,但是它要求程序员编写的代码较多,且需要管理所有系统提供给程序

IT小虫站点 511

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

【Win32 多线程程序设计基础第一章笔记】

在计算机技术的演进中,“线程(Thread)” 始终处于 “被重视却易被误解” 的特殊地位。正如《Win32 多线程程序设计》第一章开篇所言:“计算机工业界每有新技术问世,人们总是先担忧其重要性,直到竞争对手采用才急急赶上;最终用户觉得需要它,却未必了解它是什么。” 线程技术正是如此 —— 它并非新事物,却借着 Windows NT 与 Windows 95 的庞大装机量,首次从操作系统教科书的理论概念,普及为个人电脑程序设计的核心工具。从术语定义来看,线程是比进程(Process)更小的执行单元。

云小逸的博客 1034

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

(转载)win32多线程的性能

Win32 多线程的性能出处:MicrosoftRuediger R. AscheMicrosoft Developer Network 技术小组 摘要本文讨论将单线程应用程序重新编写成多线程应用程序的策略。它以Microsoft Windows 95和Windows NT的平台为例,从吞吐量(throughput)和响应方面,与兼容的单线程计算相比较而分析了多线程计算的性能。介绍在您

星光中的灯 4069

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

多线程的几个简单问题

VC中多线程使用比较广泛而且实用,在网上看到的实例.感觉写的挺好。拿出来和大家分享下 一、问题的提出 编写一个MFC的应用程序,在对话框上显示系统当前时间 例1 1.单线程显示系统时间 如果不采用多线程的方式,则需要一个计时器来控制对话框的界面刷新。具体做法如下 1)新建一个基于对话框的应用程序SingleThread; 2)在主对话框上添加一个Button和一个edit控件,将

云鹏2013的专栏 3073
上一篇: 【Win32多线程】异步I/O技术(Overlapped I/O),避免使用多线程
下一篇: 【Win32多线程】使用C runtime Library
xiaoding133
博客等级 码龄19年 415粉丝 159原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值