如何在Python中运行音频与GDI PATCOPY效果且避免音频中断
问题分析与解决方案
问题核心在于GDI线程是CPU密集型任务,50000次无停顿的PATCOPY操作几乎占满CPU时间片,导致音频线程抢不到执行机会;加上线程默认优先级相同,winsound的阻塞Beep调用被频繁打断。另外你的GDI代码还存在资源释放错误,会加剧系统资源紧张。
具体修复步骤:
1. 提高音频线程优先级
给音频线程设置更高的系统优先级,让系统优先处理音频任务:
# 需要额外导入 from win32api import SetThreadPriority, GetCurrentThread from win32con import THREAD_PRIORITY_HIGHEST def func1(): import winsound # 设置当前线程为最高优先级 SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST) freq = 500 dur = 1000 # ... 其余蜂鸣参数不变 winsound.Beep(freq, dur) # ... 其余Beep调用不变
2. 优化GDI循环,增加微小延迟
在GDI循环中加入Sleep(0),让当前线程主动放弃剩余时间片,给音频线程执行机会:
def func2(): desk = GetDC(0) x = GetSystemMetrics(0) y = GetSystemMetrics(1) print(x, y) for i in range(50000): brush = CreateSolidBrush(RGB( randrange(255), randrange(255), randrange(255) )) SelectObject(desk, brush) PatBlt(desk, randrange(x), randrange(y), randrange(100), randrange(200), PATCOPY) DeleteObject(brush) # 主动让出CPU时间片 Sleep(0) # 修复资源释放:GetDC获取的DC用ReleaseDC释放,参数顺序是窗口句柄+DC句柄 ReleaseDC(0, desk) # GetDC获取的DC不需要DeleteDC,只有CreateDC创建的才需要
3. 修复GDI资源释放错误
原来的ReleaseDC(desk, GetDesktopWindow())参数顺序完全错误,正确的调用是ReleaseDC(0, desk)(因为GetDC(0)是获取屏幕的DC,窗口句柄为0),并且不需要调用DeleteDC(该函数仅用于释放CreateDC创建的设备上下文)。
修改后的完整代码
from threading import Thread import os from win32gui import * from win32api import * from win32ui import * from win32con import * from random import * from win32api import SetThreadPriority, GetCurrentThread from win32con import THREAD_PRIORITY_HIGHEST def func1(): import winsound # 设置音频线程为最高优先级 SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST) freq = 500 dur = 1000 freq1 = 600 dur1 = 200 freq2 = 100 dur2 = 100 freq3 = 900 dur3 = 120 freq4 = 700 dur4 = 3000 freq5 = 9000 dur5 = 100 freq6 = 5000 dur6 = 500 freq7 = 700 dur7 = 700 freq8 = 900 dur8 = 400 freq9 = 300 dur9 = 900 winsound.Beep(freq, dur) winsound.Beep(freq1, dur1) winsound.Beep(freq2, dur2) winsound.Beep(freq3, dur3) winsound.Beep(freq4, dur4) winsound.Beep(freq5, dur5) winsound.Beep(freq6, dur6) winsound.Beep(freq7, dur7) winsound.Beep(freq8, dur8) winsound.Beep(freq9, dur9) def func2(): desk = GetDC(0) x = GetSystemMetrics(0) y = GetSystemMetrics(1) print(x, y) for i in range(50000): brush = CreateSolidBrush(RGB( randrange(255), randrange(255), randrange(255) )) SelectObject(desk, brush) PatBlt(desk, randrange(x), randrange(y), randrange(100), randrange(200), PATCOPY) DeleteObject(brush) # 让出CPU时间片,给音频线程执行机会 Sleep(0) # 正确释放DC ReleaseDC(0, desk) if __name__ == '__main__': Thread(target=func1).start() Thread(target=func2).start()
内容的提问来源于stack exchange,提问作者SkyKrye
相关产品推荐
相关产品推荐

