多线程及聊天室程序

2023-05-16

1.一个多线程程序

新建一个win32 console application,取名:MultiThread,选空的工程,并建立一个名为MultiThread的源文件编辑:

#include   
#include   
#include   
 
DWORD WINAPI Fun1Proc(LPVOID  lpParameter); 
 
int index= 0
void  main() 

    HANDLE hThread1; 
    hThread1=CreateThread(NULL, 0,Fun1Proc,NULL, 0,NULL); 
    CloseHandle(hThread1); 
     while(index++< 1000
        cout<< "main thread is running"<
     //Sleep(10);//
让主线程暂停运行10毫秒 
     

 
DWORD WINAPI Fun1Proc(LPVOID  lpParameter) 

    while(index++<1000
        cout<<"thread1 is running"<
     return  0
}

 

2.模拟火车站的售票系统

#include   
#include   
#include   
 
DWORD WINAPI Fun1Proc(LPVOID  lpParameter); 
DWORD WINAPI Fun2Proc(LPVOID  lpParameter); 
 
 
int index= 0
int tickets= 100; //
指定的票数 
HANDLE hMutex;//
定义一个互斥对象句柄 
 
void main() 

    HANDLE hThread1; 
    HANDLE hThread2; 
    hThread1=CreateThread(NULL,0,Fun1Proc,NULL,0,NULL); 
    hThread2=CreateThread(NULL,0,Fun2Proc,NULL,0,NULL); 
    CloseHandle(hThread1); 
    CloseHandle(hThread2); 
//    while(index++<1000) 
//        cout<<"main thread is running"<
    //Sleep(10);//
让主线程暂停运行10毫秒 
 
    //hMutex=CreateMutex(NULL,FALSE,NULL);//
创建一个匿名的互斥对象,FALSE指定主线程不拥有互斥对象  
    //hMutex=CreateMutex(NULL,TRUE,NULL);//
创建互斥对象时,就把这个对象分配给了主线程,并把线程ID也设置成了
    hMutex=CreateMutex(NULL,TRUE,"tickets"); 
    if(hMutex) //
利用命名互斥的特性,可以使应用程序只能打开一个实例 
    { 
        if(ERROR_ALREADY_EXISTS==GetLastError()) 
        { 
            cout<<"only instance can run!"<
             return ; 
        } 
    } 
    WaitForSingleObject(hMutex,INFINITE); //
主线程再次请求互斥对象,此时线程ID变成
    ReleaseMutex(hMutex); 
    //
释放互斥对象,线程ID1后,变成1,互斥对象仍然没有变为已通知状态,仍然属于主线性,所以子线程没有机会执行 
    ReleaseMutex(hMutex); 
    //
再次释放互斥对象,线程ID再减1,变成0,互斥对象变为已通知状态,此时子线程可以调用这个互斥对象 
 
    //
保证在两个子线程卖完100张票之前不能退出 
    Sleep(4000);//
让主线程睡眠4秒钟,此时主线程不占用CPU的执行时间,处于等待状态 

DWORD WINAPI Fun1Proc(LPVOID  lpParameter) 

    //while(index++<1000) 
    //    cout<<"thread1 is running"<
/*    while(TRUE) //
断的销售火车票 
    
        //ReleaseMutex(hMutex); 
        WaitForSingleObject(hMutex,INFINITE); 
        //ININITE
指定在等待的互斥对象变为有信号之前一直等待 
        if(tickets>0) 
        
            //Sleep(1);//
在未添加互斥对象时,睡眠使它进入另一个线程 
            cout<<"thread1 sell ticket:"< <
        
        else 
            break; 
        ReleaseMutex(hMutex);//
释放互斥对象 
    
*/ 
    WaitForSingleObject(hMutex,INFINITE); 
    cout<<"thread1 is running !"<
     //
线程终止后,操作系统会自动将互斥对旬的引用计数和线程ID设为
    return 0

 
DWORD WINAPI Fun2Proc(LPVOID  lpParameter) 

/*    while(TRUE)  //
不断的销售火车票 
    
        //ReleaseMutex(hMutex); 
        WaitForSingleObject(hMutex,INFINITE); 
        //ININITE
指定在等待的互斥对象变为有信号之前一直等待 
        if(tickets>0) 
        
            //Sleep(1); 
            //
在未添加互斥对象时,睡眠使它进入另一个线程,这样出现了卖出第0张票 
            cout<<"thread2 sell ticket:"< <
        
        else 
            break; 
        ReleaseMutex(hMutex);//
释放互斥对象 
    
*/ 
    WaitForSingleObject(hMutex,INFINITE); 
    cout<<"thread1 is running !"<
     return  0
}

 

3.多线程实现网络聊天室程序

编写接收端:

新建一个MFC的基于对话框的应用程序,取名为Chat,再编辑对话框资源,如图:

CChatApp::InitInstance()函数中编辑:

BOOL CChatApp::InitInstance() 

    if(
AfxsocketInit())//加载套接字 
    { 
        AfxMessageBox("
载套接字失败!"); 
        return FALSE; 
    }
 
    AfxEnableControlContainer(); 
    .......... 
    ..........

并在头文件stdafx.h预编译后边,添加头文件:

#include // 包含要用到的套接字函数的头文件

再在CChatDlg类上添加一个私有成员变量:

SOCKET m_socket;

和一个成员函数BOOL CChatDlg::InitSocket(),编辑:

BOOL CChatDlg::InitSocket() 

    m_socket=socket(AF_INET,SOCK_DGRAM,0);//
创建数据报套接字 
    if(INVALID_SOCKET==m_socket)//
判断套接字是否创建成功 
    { 
        MessageBox("
套接字创建失败!"); 
        return FALSE; 
    } 
    SOCKADDR_IN addrSock; 
    addrSock.sin_family=AF_INET; 
    addrSock.sin_port=htons(6000); 
    addrSock.sin_addr.S_un.S_addr=htonl(INADDR_ANY); 
 
    int retval; 
    retval=bind(m_socket,(SOCKADDR*)&addrSock,sizeof(SOCKADDR)); 
    if(SOCKET_ERROR==retval) 
    { 
        closesocket(m_socket); 
        MessageBox("
绑定失败!"); 
        return FASLE; 
    } 

return TRUE;
}

并在CChatDlg::OnInitDialog()中添加:

BOOL CChatDlg::OnInitDialog() 

    .......... 
    .......... 
 
    // Set the icon for this dialog.  The framework does this automatically 
    //  when the application's main window is not a dialog 
    SetIcon(m_hIcon, TRUE);            // Set big icon 
    SetIcon(m_hIcon, FALSE);        // Set small icon 
     
    // TODO: Add extra initialization here 
    InitSocket();//
初始化套接字 
    RECVPARAM *pRecvParam=new RECVPARAM;//new
一个结构体指针 
    pRecvParam->sock=m_socket; 
    pRecvParam->hwnd=m_hWnd;//
给结构体的成员初始化 
    HANDLE hThread=CreateThread(NULL,0,RecvProc,(LPVOID)pRecvParam,0,NULL);//
创建一个线程 
    CloseHandle(hThread);//
关闭线程句柄 
    return TRUE;  // return TRUE  unless you set the focus to a control }

ChatDlg.h中添加一个结构体:

struct RECVPARAM

{

    SOCKET sock;

    HWND hwnd;

};

 

并在CChatDlg添加一个静态的成员函数:

public
    static DWORD WINAPI RecvProc(LPVOID lpParameter);

并在ChatDlg.cpp编辑:

DWORD WINAPI CChatDlg::RecvProc(LPVOID lpParameter)//线程函数 

    SOCKET sock=((RECVPARAM*)lpParameter)->sock;//
套接字 
    HWND hwnd=((RECVPARAM*)lpParameter)->hwnd;//
对话框句柄 
    SOCKADDR_IN addrFrom; 
    int len=sizeof(SOCKADDR); 
 
    char recvBuf[200]; 
    char tempBuf[300]; 
    int retval; 
    while(TRUE) 
    { 
        retval=recvfrom(sock,recvBuf,200,0,(SOCKADDR*)&addrFrom,&len); 
        if(SOCKET_ERROR==retval) 
            break
        sprintf(tempBuf,"%s
说:%s",inet_ntoa(addrFrom.sin_addr),recvBuf); 
        ::PostMessage(hwnd,WM_RECVDATA,0,(LPARAM)tempBuf);//
将接收到字符传递到对话框句柄 
    } 
    return 0
}

ChatDlg.h

#define WM_RECVDATA WM_USER+1  //定义消息 
    .......... 
    .......... 
 
    // Generated message map functions 
    //{{AFX_MSG(CChatDlg) 
    virtual BOOL OnInitDialog(); 
    afx_msg void OnSysCommand(UINT nID, LPARAM lParam); 
    afx_msg void OnPaint(); 
    afx_msg HCURSOR OnQueryDragIcon(); 
    //}}AFX_MSG 
    afx_msg void OnRecvData(WPARAM wParam,LPARAM lParam);//
消息响应函数原型声明  
    DECLARE_MESSAGE_MAP()

并在ChatDlg.cpp中添加消息映射:

BEGIN_MESSAGE_MAP(CChatDlg, CDialog) 
    //{{AFX_MSG_MAP(CChatDlg) 
    ON_WM_SYSCOMMAND() 
    ON_WM_PAINT() 
    ON_WM_QUERYDRAGICON() 
    //}}AFX_MSG_MAP 
    ON_MESSAGE(WM_RECVDATA,OnRecvData)  //
消息映射 
END_MESSAGE_MAP() 

ChatDlg.cpp中添加函数CChatDlg::OnRecvData(WPARAM wParam,LPARAM lParam)

void CChatDlg::OnRecvData(WPARAM wParam,LPARAM lParam)//消息响应函数的实现 

    CString str=(char*)lParam;//
取出由消息传来的数据 
    CString strTemp; 
    GetDlgItemText(IDC_EDIT_RECV,strTemp);//
将接收编辑框中的文本存到strTemp 
    str+="/r/n"
    str+=strTemp;//
加上先前的数据 
    SetDlgItemText(IDC_EDIT_RECV,str);//
将数据设置到编辑框 
}
 

运行,OK !

 

编写发送端:

双击发送按钮,生成消息响应函数,编辑:

void CChatDlg::OnBtnSend() //发送按钮消息响应函数 

    // TODO: Add your control notification handler code here 
    DWORD dwIP; 
    ((CIPAddressCtrl*)GetDlgItem(IDC_IPADDRESS1))->GetAddress(dwIP);//
得到IP控制中的IP地址 
 
    SOCKADDR_IN addrTo; 
    addrTo.sin_family=AF_INET; 
    addrTo.sin_port=htons(6000); 
    addrTo.sin_addr.S_un.S_addr=htonl(dwIP); 
 
    CString strSend; 
    GetDlgItemText(IDC_EDIT_SEND,strSend);//
将发送编辑框控件中的数据存到strSend 
    sendto(m_socket,strSend,strSend.GetLength()+1,0
        (SOCKADDR*)&addrTo,sizeof(SOCKADDR));//
发送套接字 
    SetDlgItemText(IDC_EDIT_SEND,"");
 
}

让接收编辑框支持多行文本,将IDC_EDIT_RECV编辑框的多行属性选中即可,运行,OK!

--------------------------------------------------------------------------------

CreateThread

The CreateThread function creates a thread to execute within the virtual address space of the calling process.

To create a thread that runs in the virtual address space of another process, use the CreateRemoteThread function.

HANDLE CreateThread(

LPSECURITY_ATTRIBUTES lpThreadAttributes, // SD

SIZE_T dwStackSize, // initial stack size

LPTHREAD_START_ROUTINE lpStartAddress, // thread function

LPVOID lpParameter, // thread argument

DWORD dwCreationFlags, // creation option

LPDWORD lpThreadId // thread identifier

);

Parameters

lpThreadAttributes

[in] Pointer to a SECURITY_ATTRIBUTES structure that determines whether the returned handle can be inherited by child processes. If lpThreadAttributes is NULL, the handle cannot be inherited.

Windows NT/2000/XP: The lpSecurityDescriptor member of the structure specifies a security descriptor for the new thread. If lpThreadAttributes is NULL, the thread gets a default security descriptor.

dwStackSize

[in] Specifies the initial size of the stack, in bytes. The system rounds this value to the nearest page. If this parameter is zero, the new thread uses the default size for the executable. For more information, see Thread Stack Size.

lpStartAddress

[in] Pointer to the application-defined function of type LPTHREAD_START_ROUTINE to be executed by the thread and represents the starting address of the thread. For more information on the thread function, see ThreadProc.

lpParameter

[in] Specifies a single parameter value passed to the thread.

dwCreationFlags

[in] Specifies additional flags that control the creation of the thread. If the CREATE_SUSPENDED flag is specified, the thread is created in a suspended state, and will not run until the ResumeThread function is called. If this value is zero, the thread runs immediately after creation. At this time, no other values are supported.

Windows XP: If the STACK_SIZE_PARAM_IS_A_RESERVATION flag is specified, the dwStackSize parameter specifies the initial reserve size of the stack. Otherwise, dwStackSize specifies the commit size.

lpThreadId

[out] Pointer to a variable that receives the thread identifier.

Windows NT/2000/XP: If this parameter is NULL, the thread identifier is not returned.

Windows 95/98/Me: This parameter may not be NULL.

Return Values

If the function succeeds, the return value is a handle to the new thread.

If the function fails, the return value is NULL. To get extended error information, call GetLastError.

Note that CreateThread may succeed even if lpStartAddress points to data, code, or is not accessible. If the start address is invalid when the thread runs, an exception occurs, and the thread terminates. Thread termination due to a invalid start address is handled as an error exit for the thread's process. This behavior is similar to the asynchronous nature of CreateProcess, where the process is created even if it refers to invalid or missing dynamic-link libraries (DLLs).

Windows 95/98/Me: CreateThread succeeds only when it is called in the context of a 32-bit program. A 32-bit DLL cannot create an additional thread when that DLL is being called by a 16-bit program.

Remarks

The number of threads a process can create is limited by the available virtual memory. By default, every thread has one megabyte of stack space. Therefore, you can create at most 2028 threads. If you reduce the default stack size, you can create more threads. However, your application will have better performance if you create one thread per processor and build queues of requests for which the application maintains the context information. A thread would process all requests in a queue before processing requests in the next queue.

The new thread handle is created with THREAD_ALL_ACCESS to the new thread. If a security descriptor is not provided, the handle can be used in any function that requires a thread object handle. When a security descriptor is provided, an access check is performed on all subsequent uses of the handle before access is granted. If the access check denies access, the requesting process cannot use the handle to gain access to the thread. If the thread impersonates a client, then calls CreateThread with a NULL security descriptor, the thread object created has a default security descriptor which allows access only to the impersonation token's TokenDefaultDacl owner or members. For more information, see Thread Security and Access Rights.

The thread execution begins at the function specified by the lpStartAddress parameter. If this function returns, the DWORD return value is used to terminate the thread in an implicit call to the ExitThread function. Use the GetExitCodeThread function to get the thread's return value.

The thread is created with a thread priority of THREAD_PRIORITY_NORMAL. Use the GetThreadPriority and SetThreadPriority functions to get and set the priority value of a thread.

When a thread terminates, the thread object attains a signaled state, satisfying any threads that were waiting on the object.

The thread object remains in the system until the thread has terminated and all handles to it have been closed through a call to CloseHandle.

The ExitProcess, ExitThread, CreateThread, CreateRemoteThread functions, and a process that is starting (as the result of a call by CreateProcess) are serialized between each other within a process. Only one of these events can happen in an address space at a time. This means that the following restrictions hold:

  • During process startup and DLL initialization routines, new threads can be created, but they do not begin execution until DLL initialization is done for the process.
  • Only one thread in a process can be in a DLL initialization or detach routine at a time.
  • ExitProcess does not return until no threads are in their DLL initialization or detach routines.

A thread that uses functions from the C run-time libraries should use the beginthread and endthread C run-time functions for thread management rather than CreateThread and ExitThread. Failure to do so results in small memory leaks when ExitThread is called.

Example Code

For an example, see Creating Threads.

Requirements

  Windows NT/2000/XP: Included in Windows NT 3.1 and later.
  Windows 95/98/Me: Included in Windows 95 and later.
  Header: Declared in Winbase.h; include Windows.h.
  Library: Use Kernel32.lib.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

多线程及聊天室程序 的相关文章

  • [微服务感悟] 服务雪崩与熔断器

    文章目录 什么是服务雪崩解决方式熔断器舱壁模式 服务隔离 什么是服务雪崩 之前工作中出现了这样的一个问题 xff0c 有一个业务服务 xff0c 它的功能是政府某部门的文件流转柜 那个业务中原本每个外部请求都有一个独立的线程池去处理任务 x
  • [微服务感悟] 很好理解的分布式事务

    事务是保证一系列操作是一个整体 xff0c 要么都执行 xff0c 要么都不执行 比如A给B转账 xff0c A扣钱了 xff0c B的账户的钱也要加上去 xff0c 不能出现A扣钱B不加钱 xff0c 或者B加钱A不扣钱的情况 在单体程序
  • 参加2020Jam初赛记录与部分题目解答

    Google Jam大赛是谷歌举办的一年一届的在线答算法题的的比赛 初赛比赛时长27小时 xff0c 一共有5道算法题 xff0c 总分100分 xff0c 获得分数30分和以上者 xff0c 就能晋级下一轮比赛 在这27小时内 xff0c
  • Cannot add task wrapper as a task with that name already exists - 问题解决

    问题描述 项目使用 gradle build 去打包 xff0c 报错 Cannot add task 39 wrapper 39 as a task with that name already exists xff0c 使用 gradl
  • K3s 无法下载镜像 failed to authorize/ failed to fetch anonymous token/ unexpected status/ 401 Unauthorized

    我需要部署公司功能节点进行测试 xff0c 考虑自己的 mac pro 内存很小只有 16g xff0c k8s 运行需要大量内存 xff0c 电脑可能要卡死 周边同学推荐装 k3s xff0c 它可以看作 k8s 的精简版 xff0c 删
  • 一看就懂的 RabbitMQ 使用教程

    一天 xff0c 阿强接到一个需求 xff0c 将公网的服务的执行结果通知到内网的服务上 阿强一想 xff0c 很简单阿 xff0c 只要在公网搭一个简单的消息服务 xff0c 给公网系统提供一个存储消息接口 xff1b 给内网系统提供一个
  • OOM 很可怕吗 -- minio-client 上传文件触发 OOM 排错

    不要把 OOM 问题当作一个可怕的难题 xff0c 也许对着报错堆栈日志看代码就能解决 问题描述 线上服务出现 OOM 的日志 xff0c 日志显示是 minio client 的错误 使用 minio client 版本是 3 0 10
  • AI 写代码来了 - github 的 AI 写代码插件 copilot 发布

    以前老在调侃 AI 自动写代码 xff0c 没想到这么快就成现实 这几天 github 出了 AI 写代码插件 xff0c 支持 vscode 编辑器 xff0c js xff0c py xff0c go 等语言 xff0c 看了介绍 xf
  • 枚举与字符串的转换

    枚举类型的使用优势没啥好说的 但经常需要将它与字串进行转换方便显示或其它需求 1 将枚举中的标示转成字符串 xff1a define enumToString value 64 value 将枚举转换成字符串 2 在常见的方案中 xff0c
  • springcloud trace SDK 自研方案

    SDK 形式 xff0c 利用 threadlocal 实现 trace http grpc rabbitMQ springcloud gateway 异步线程池这类常见场景 客户端在协议 header 中增加 x request id x
  • fluent-bit 按 pod 名生成不同索引

    1 实现效果 如果 pod 名为 prod xff0c 输出索引名为 prod 2021 01 24 EFK 版本 xff1a es 7 12 fluent bit 1 7 5 kibana 7 12 2 实现方式 读取日志数据中 kube
  • jar 迁移 mvn 私有库

    将 jar 从一个 mvn 库迁移另一个 mvn 库的办法 1 拉取 jar 到本地 mvn 库 创建拉取项目文件夹 xff0c 文件夹下创建 pom xml xff0c settings xml 两个文件 xff0c 填写要迁移的 jar
  • Elasticsearch 解决 log4j 安全漏洞 - 升级镜像

    一 概论 Apache Log4j 2 被披露出存在严重代码执行漏洞 xff0c 目前官方已发布正式安全公告及版本 xff0c 漏洞编号 xff1a CVE 2021 44228 xff0c 漏洞被利用可导致服务器被入侵等危害 公司 ES
  • Prometheus 实现 podDown 实时告警

    一 需求 每个 pod 重启 删除时 xff0c 都能发出告警 要及时和准确 二 告警架构 集群部署在 k8s 上 xff0c 告警使用 Prometheus 43 alertManager 43 prometheusManager xff
  • prometheus 告警机制 -(为什么告警发的不及时)

    为什么告警有时发的及时 xff0c 有时发的慢 数据异常到监控发出告警的时间与多个参数相关 xff0c 包括采集间隔 xff0c 扫描间隔 xff0c group 发送间隔 xff0c 告警持续时间 for 等 最长的时间为 采集间隔 43
  • prometheus 告警机制 - 我的告警为什么重发

    为什么告警总在重复发 xff0c 有时不重复发 xff0c 怎么避免 告警会在两种情况下重发 告警 group 列表中告警有变更 xff08 增加或者减少 xff09 告警持续到 repeat interval 配置的重发时间 告警 gro
  • linux 盘格式化并挂载

    一 概论 如果 linux 要格式化盘 xff0c 需要先解挂 xff0c 才能格式化 xff0c 格式化的速度比 rm rf 会快 xff0c 作用一样 如果是初始化机器挂载盘 xff08 不要解绑操作 xff09 xff0c 直接查看第
  • grafana 画富集多个指标 label 的表格

    下午5点 xff1a 老哥 xff0c 今天把业务趋势图搞出来吧 一 怎么画表格 我们的需要是做下面的视图 xff0c 他是一个表格 xff0c 而且有着多个数据源 添加图表 填入数据 xff0c 展示原始图形 转换为 table 只显示最
  • [golang] 实现 jwt 方式登录

    1 Jwt 和 Session 登录方案介绍 JSON Web Token xff08 缩写 JWT xff09 是目前流行的跨域认证解决方案 原理是生存的凭证包含标题 header xff0c 有效负载 payload 和签名组成 用户信
  • Stochastic Light Culling for VPLs on GGX Microsurfaces论文研读

    前言 好久没写博客了 xff0c 今天来共享一下最近研读的一篇论文吧 xff0c 文章中 pdf 为参考文献可自行谷歌学术下载 因为本人还是个图形学菜鸟 xff0c 所以有什么问题希望大家多多指正 Stochastic Light Cull

随机推荐

  • 瞎更新,container_cpu_usage_seconds_total{job=“cadvisor“} 怎么没有啦

    一 基本介绍 1 1 概论 1 1 1 故事背景 今天在同步其他团队的 grafana 监控大盘时 xff0c Prometheus 服务报告说不能找到名为 container cpu usage seconds total job 61
  • Prometheus MySQL 性能监控

    一 介绍 Prometheus 是一种开源的监控系统和时序数据库 xff0c 旨在收集和处理大量数据并提供可视化 监控警报等功能 它支持多种语言 多种部署方式 xff0c 并且非常灵活 xff0c 而且社区支持非常活跃 xff0c 为用户提
  • 二、nodeJS 项目架构详解(app.js + Express + Http)

    参考 xff1a https www cnblogs com ostrich sunshine p 7474471 html 其中重点文件 文件夹说明 xff1a techNode xff1a bin www 启动运行 xff08 服务端口
  • centos 安装freeswitch

    首先安装freeswitch的运行库 更新yum yum update 安装依赖 yum install y git gcc c 43 43 wget alsa lib devel autoconf automake bison broad
  • Visio、Matlab高清图片插入word文档的几种方法。

    2023 3 30 直接参考这两个就行了 xff0c 不用花里胡哨的 MATLAB 1 重要的第一步 xff0c 另存为png图片 xff1b 2 导出之前先设置分辨率 xff0c 很多期刊要求600dpi 这一步很关键 Visio 1 重
  • CTF Crypto---RSA NC不互素

    题目 span class token keyword from span Crypto span class token punctuation span Util span class token punctuation span nu
  • 看一看Ubuntu的目录结构

    先了解一下Ubuntu的目录结构 xff0c 对于后面学习Ubuntu软件安装和使用都有帮助 一 Linux没有盘符这个概念 Windows存在多个驱动器盘符 xff0c 每个盘符形成多个树形并列的情形 xff0c Linux没有盘符这个概
  • 【C语言】——结构体进阶:结构体的内存对齐(超详细)

    前言 xff1a 上一篇已经讲了结构体的基本用法 相信各位小伙伴以经学会怎么使用 但是还有一个问题没有弄明白 结构体到底多大 xff0c 占内存空间多不多 xff0c 以经系统到底怎么访问结构体内的数据的 接下来 xff0c 详细分析一下结
  • [OpenCV实战]15 基于深度学习的目标跟踪算法GOTURN

    目录 1 什么是对象跟踪和GOTURN 2 在OpenCV中使用GOTURN 3 GOTURN优缺点 4 参考 在这篇文章中 xff0c 我们将学习一种基于深度学习的目标跟踪算法GOTURN GOTURN在Caffe中搭建 xff0c 现在
  • **在Linux的shell脚本里激活conda 虚拟环境**

    在Linux的shell脚本里激活conda 虚拟环境 之前突发其想 xff0c 既然在命令行可以通过conda activate tf激活tf的虚拟环境 xff0c 那么能不能写个脚本实现呢 xff1f 费了好大劲 xff0c 发现并不行
  • Hierarchical Russian Roulette for Vertex Connections论文研读

    第二篇论文研读文章了 xff0c 虽然依旧很菜 xff0c 但这一篇开始就相对轻松一点了 文档种有些问题 xff0c 其中所有 实时 应该替换为 高效 Hierarchical Russian Roulette for Vertex Con
  • ARM通用中断控制器GIC之中断控制

    在阅读本章之前 xff0c 可以参考笔者之前关于GIC的一些描述 xff1a ARM通用中断控制器GIC generic Interrupt Controller 简介 ARM架构Generic Interrupt Controller G
  • 最小生成树之Kruskal算法

    给定一个无向图 xff0c 如果它任意两个顶点都联通并且是一棵树 xff0c 那么我们就称之为生成树 Spanning Tree 如果是带权值的无向图 xff0c 那么权值之和最小的生成树 xff0c 我们就称之为最小生成树 MST Min
  • xcode11解决:xcode multiple commands produce .../xxx/Assets.car

    最近在xcode 11上使用pod碰到一个问题 xff0c Assets car被生成多次 问题如下 xff1a Multiple commands produce 39 Users luowei Library Developer Xco
  • 算法 —— 冒泡排序

    冒泡排序 冒泡排序是比较两个相邻元素 xff0c 如果它们不符合预期的顺序就交换的一个排序过程 冒泡排序就像水中气泡上升到水面的运动一样 xff0c 数组的每个元素在每次迭代中都把当前迭中最大 或最小 的元素移动到最后 xff0c 因此被称
  • UICollectionView viewForSupplementaryElementOfKind 不调用

    发现UICollectionView 的 方法不调用 func collectionView collectionView UICollectionView viewForSupplementaryElementOfKind kind St
  • UICollectionViewCell 自动大小的两种常用方式

    方法一 xff1a 自动计算 override func viewDidLoad super viewDidLoad if let flowLayout 61 collectionView collectionViewLayout as U
  • UITableViewCell 图片自适应

    常见的一种方法是异步Completed时 xff0c 根据图片大小计算cell的高度并缓存到字典里后 xff0c 刷新tableView或indexPath 但这里介绍另一种更好的方式是使用约束处理 xff0c 对imageView的上下左
  • Swift编译死锁问题

    最近在Swift OC混编项目里遇到个奇怪的问题 xff0c 这样一行代码尽然引发了Swift编译过程死锁 xxSwiftModel salary 61 xxOCModel salary doubleValue 如果哪位大神知道根因 xff
  • 多线程及聊天室程序

    1 一个多线程程序 新建一个 win32 console application 取名 xff1a MultiThread 选空的工程 xff0c 并建立一个名为 MultiThread 的源文件编辑 xff1a include inclu