解决控制台假死问题

本文介绍了VS控制台中快速编辑模式导致的问题,即点击窗口内容暂停程序运行。提供了解决方案,包括关闭快速编辑模式、使用MAPI设置控制台模式以及自定义按键控制编辑模式。测试代码展示了如何在主程序中应用这些技巧。

1.问题和需求

解决 不小心点击窗口内容就会导致控制台进程、打印等暂停的问题

2.原因

VS控制台默认提供的暂停功能导致,即默认打开了快速编辑模式,此模式下点击窗口内内容会暂停控制台程序的运行。

3.解决方案

  1. 每次运行时对有需要的exe程序关闭快速编辑模式。

    • 运行时选择当前exe程序窗口上方的边框栏 —> 右键 —>属性 —> 取消勾选快速编辑模式
    • 弊端:对于多窗口、多用户使用的实际程序来说不现实。仅推荐测试使用
  2. 使用MAPI的方式设置控制台模式,移除快速编辑模式,代码如下:

    //关闭控制台程序的快速编辑模式,否则会出现点击界面,程序将会变成阻塞状态,不按回车无法继续运行
    void CloseQuickEditMode() {
    	HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE); // 获取句柄
    	DWORD mode;
    	GetConsoleMode(hStdin, &mode); //获取当前控制台模式
    	mode &= ~ENABLE_QUICK_EDIT_MODE;  //移除快速编辑模式
    	SetConsoleMode(hStdin, mode); //设置修改后的控制台模式
    }
    
    • 推荐使用这种方法。多窗口使用时,将此方法封装在工具库中,在每个窗口逻辑代码最前面调用此函数即可

    • 如还需增加/移除其他模式(如插入模式),可以参考MSDN :
      在这里插入图片描述
      注意:以上解决方案关闭快速编辑模式以后,控制台将变为不可选模式,即也无法进行选中内容复制等操作

4.测试代码

//关闭控制台程序的快速编辑模式,否则会出现点击界面,程序将会变成阻塞状态,不按回车无法继续运行
void CloseQuickEditMode() {
	HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE); // 获取句柄
	DWORD mode;
	GetConsoleMode(hStdin, &mode); //获取当前控制台模式
	mode &= ~ENABLE_QUICK_EDIT_MODE;  //移除快速编辑模式
	SetConsoleMode(hStdin, mode); //设置修改后的控制台模式
}

int main() {
	// 关闭控制台程序的快速编辑模式
	CLoseQuickEditMode();
    
	int ch, i = 0;

	while (1) {
        //测试使用f1-f10
		if (_kbhit()) {
			ch = _getch();
			if (ch == 27) { break; }//当按下ESC时退出循环
			if (ch == 59) printf("F1\n");
			if (ch == 60) printf("F2\n"); 
			if (ch == 61) printf("F3\n");
			if (ch == 62) printf("F4\n");
			if (ch == 63) printf("F5\n"); 
			if (ch == 64) printf("F6\n"); 
			if (ch == 65) printf("F7\n");
			if (ch == 66) printf("F8\n"); 
			if (ch == 67) printf("F9\n"); 
			if (ch == 68) printf("F10\n"); 
		}

		Sleep(1000);
		cout << "test: " << i++ << endl;	
	}

	system("pause");

	return 0;
}

运行结果:
在这里插入图片描述

5.部分控制台需要选择文本复制的问题

​ 由于“快速编辑模式”是windows系统自带的,打开即可选中控制台中的内容进行操作,但是系统也会对应的挂起程序(即暂停),这个操作与快速编辑模式绑定,暂未找到可分离的方式。

解决思路:

  1. 需要“可选择控制台内容”的可执行程序数量 > 不需要的

    • 使用 某个按键开启/关闭快速编辑功能,以下示例代码使用了“y”键

    • void UpdateQuickEditMode(int i) {
      	HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE);
      	DWORD mode;
      	GetConsoleMode(hStdin, &mode);
      	
      	//默认 关闭
      	mode &= ~ENABLE_QUICK_EDIT_MODE;  //移除快速编辑模式
          if (i & 1) { //奇数 打开
      		mode = ENABLE_QUICK_EDIT_MODE;
      	}
      
      	SetConsoleMode(hStdin, mode);
      }
      
      void testEdit() {
      	int key;
      	int i = 0;
      	UpdateQuickEditMode(i++);
          
      	while (true) {
      		if (_kbhit()) {//如果有按键按下,则_kbhit()函数返回真
      			key = _getch();//使用_getch()函数获取按下的键值
      			cout << key << endl;
      
      			if (key == 121) { // y
      				UpdateQuickEditMode(i++);
      			}
      		}
      
      		Sleep(1000);
      		cout << "Hello" << endl;
      	}
      }
      
      int main() {
      
      	testEdit();
      
      	system("pause");
      	return 0;
      }
      
    • 将工具代码写入工具库,供每一个需要的可执行程序使用。默认关闭快速编辑模式,需要时按下y键打开,不再使用按下y键关闭(也可以改为按不同的键开关)

    • 总的来说会更方便操作

  2. 需要“可选择控制台内容”的可执行程序数量 < 不需要的(如只有日志功能需要),默认全部关闭,不使用按键功能,在需要使用编辑功能时,直接按下 Ctrl+M 对内容进行选择( 或 选择 右键控制台边框栏 --> 编辑 --> 标记 对内容进行选择 )。选择内容期间后台程序挂起,不运行,按下回车键后恢复。

    • 可以 缩减空间、程序不需要一直开启等待用户输入,减少条件判断
      在这里插入图片描述
<think> 我们正在处理用户关于OpenMP在WSL上假死问题。 根据已知信息,用户遇到了在WSL(Windows Subsystem for Linux)上使用OpenMP时程序假死(挂起)的情况。 我们需要提供解决方案。 可能的原因和解决方案: 1. WSL1的局限性:WSL1在早期版本中对多线程支持不够完善,尤其是在处理大量线程时可能出现问题。建议升级到WSL2。 2. 线程亲和性(Affinity)设置:OpenMP可能会尝试设置线程亲和性,但在WSL中可能不支持或导致问题。可以设置环境变量关闭亲和性设置。 3. 线程数量设置:如果线程数量设置过多,可能导致资源争用。可以尝试限制线程数量。 4. 系统资源限制:检查WSL的内存和CPU分配是否足够。 具体步骤: 1. 确认WSL版本:运行 `wsl -l -v` 查看版本。如果是WSL1,升级到WSL2(参考微软官方文档)。 2. 设置环境变量禁用线程亲和性: 在运行程序前,设置环境变量:`export OMP_PROC_BIND=false` 和 `export OMP_PLACES=cores`(或者尝试其他值,或者不设置) 或者更彻底地:`export GOMP_CPU_AFFINITY=""`(针对GCC的OpenMP实现) 3. 限制线程数量:通过环境变量`OMP_NUM_THREADS`设置一个较小的值,例如`export OMP_NUM_THREADS=4`。 4. 调整WSL资源:在Windows用户目录下创建或修改`.wslconfig`文件(注意文件名前面有一个点),内容如下: ``` [wsl2] memory=4GB # 根据你的系统调整 processors=4 # 根据你的CPU核心数调整 ``` 然后重启WSL:在PowerShell中运行 `wsl --shutdown`,再重新启动WSL。 注意:以上环境变量设置可以在运行程序前在终端中设置,也可以写入到`~/.bashrc`中。 如果问题仍然存在,可以尝试更新WSL和Linux内核,或者检查代码中是否有死锁等问题。 引用说明:由于用户要求参考站内引用,但我们的知识库中没有具体引用来源,因此我们根据一般经验提供建议。如果用户需要更具体的引用,我们可以指出这些是OpenMP和WSL社区的常见解决方案。 生成相关问题: 1. 如何将WSL1升级到WSL2? 2. 如何调整WSL2的资源分配? 3. OpenMP环境变量有哪些常用的设置? 4. 如何调试OpenMP程序死锁问题? </think> ### OpenMP在WSL上假死解决方案 在WSL环境中使用OpenMP时出现程序假死(挂起)问题,通常与以下原因相关。以下是逐步解决方案: #### 1. **升级到WSL2** WSL1对Linux内核的模拟不完整,可能导致多线程支持异常: ```powershell # PowerShell中检查版本 wsl -l -v # 若为WSL1,升级到WSL2 wsl --set-version <发行版名称> 2 ``` 升级后重启WSL:`wsl --shutdown`[^1] #### 2. **禁用线程亲和性绑定** OpenMP默认尝试绑定线程到特定CPU核心,这在WSL虚拟化环境中易引发问题: ```bash # 临时设置环境变量 export OMP_PROC_BIND=false export GOMP_CPU_AFFINITY="" # 或在代码中设置 #include <omp.h> omp_set_num_threads(4); // 限制线程数 omp_set_dynamic(0); // 关闭动态调整 omp_set_schedule(omp_sched_static, 0); // 使用静态调度 ``` #### 3. **调整线程数量** 避免创建过多线程导致资源争用: ```bash # 限制为物理核心数(非超线程数) export OMP_NUM_THREADS=$(grep 'cpu cores' /proc/cpuinfo | uniq | awk '{print $4}') ``` #### 4. **配置WSL资源分配** 在Windows用户目录创建`.wslconfig`文件: ```ini [wsl2] memory=4GB # 分配足够内存 processors=4 # 分配CPU核心 swap=2GB # 避免内存不足 ``` 保存后执行:`wsl --shutdown && wsl` #### 5. **更新组件** 确保系统组件最新: ```bash # WSL内核更新 sudo apt update && sudo apt upgrade -y # 安装最新GCC和OpenMP库 sudo apt install gcc-12 libomp-dev ``` #### 6. **验证测试** 使用简单OpenMP程序验证: ```c #include <omp.h> #include <stdio.h> int main() { #pragma omp parallel printf("Thread %d/%d\n", omp_get_thread_num(), omp_get_thread_num()); return 0; } ``` 编译运行:`gcc -fopenmp test.c -o test && ./test` > ⚠️ **注意**:若仍存在问题,尝试在Windows终端属性中禁用"使用旧版控制台"(可能导致ANSI转义序列冲突)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值