跳转到内容
View in the app

A better way to browse. Learn more.

彼岸论坛

A full-screen app on your home screen with push notifications, badges and more.

To install this app on iOS and iPadOS
  1. Tap the Share icon in Safari
  2. Scroll the menu and tap Add to Home Screen.
  3. Tap Add in the top-right corner.
To install this app on Android
  1. Tap the 3-dot menu (⋮) in the top-right corner of the browser.
  2. Tap Add to Home screen or Install app.
  3. Confirm by tapping Install.
欢迎抵达彼岸 彼岸花开 此处谁在 -彼岸论坛

[程序员] [求助] Python 调用 dll 的时候发现代码运行被阻塞了?

发表于

业务说明

使用 ctypes 对接 C++的 dll 接口,封装为 websocket 接口方便网络调用。使用了 Redis 的 PUB/SUB 来监听服务端主动发起的消息通知。

使用了 asyncio 库做异步任务来处理 websocket 的请求通知,使用 aioredis 来进行管理 Redis 连接。

案例代码

入口代码如下:

async def main():
    redis = aioredis.from_url(f'redis://:{redis_password}@{redis_host}:{redis_port}', encoding='utf-8')
    redis_task = asyncio.create_task(redis_subscriber_start_websocket(redis))
    server_task = websockets.serve(msdk_handler, "0.0.0.0", 8765)
    asyncio.create_task(monitor_loop())
    print("WebSocket 服务器启动在 ws://localhost:8765:redis 地址: ", redis_host, redis_port)
    await asyncio.gather(server_task, redis_task)
    

if __name__ == "__main__":
    asyncio.run(main())

大致的 websocket 处理流程如下:

       try:
            async for message in websocket:
                data = json.loads(message)
                # print(f"收到 websocket 消息: {data}")
                await messageHandler(data, connected[random_id_str])
            print("WebSocket 连接正常关闭")  # 添加这行来确认循环是否正常结束
            await clearnWebscoket(random_id_str)
            
     
   async def messageHandler(data, connected):
      if data['action'] == 'something':
      # 切换位置
      results = await change_something(connected['client_id'], data)
      await connected['websocket'].send(json.dumps(results))

	async def change_something(client_id):
	    future = asyncio.Future()
	    futures_change_chara_pos[client_id] = future
	    # 调用 DLL 中的更改角色位置函数
	    sdk.SDK_change_something(c_char_p(client_id.encode('utf-8')),callback_instance)    
	    while not future.done():
	        await asyncio.sleep(0)
	    result = await future
	    return result
	    
在 callback_instance 回调中,我会设置 future 的内容。

def set_futures_status(client_id, futures_obj, data):
    if client_id in futures_obj:
        future = futures_obj.pop(client_id)
        if not future.done():
            future.set_result(data)

问题

对项目的异步和 Redis 消息有点不理解。

1 、有一个播放音频的 C++接口,会频繁触发回调函数,我发现在播放音频的时候,接收了其他的 websocket 消息,发现好像没有处理,处理函数的日志没有打印出来 [偶现正常] 。不知道是不是我异步有问题,阻塞了主线程导致的。(作为一个前端开发,python 的异步好难懂,大佬们有推荐的书籍吗)

2 、Redis 消息一会后,就不会接收到订阅的消息。 消息的发布和接收频道一致,并且重启 python 后服务正常。

期望

能帮忙解决一下目前碰到的 2 个问题,特别是异步的代码,我不知道自己写的是否正确。

	    while not future.done():
	        await asyncio.sleep(0)
	    result = await future

上面的代码就是我发现 await future 后会一直阻塞主进程代码运行。所以在 AI 的提示下,加上了代码后正常运行。但是 websocket 消息处理中的 await 又不会阻塞整个主进程运行,就很疑惑。

报酬

目前预算 500 ,可谈。代码地址: https://github.com/mydaoyuan/pythonAndDll

联系方式:d29zaGl0ZHkxMjM0NTY=

Featured Replies

No posts to show

创建帐户或登录来提出意见

Configure browser push notifications

Chrome (Android)
  1. Tap the lock icon next to the address bar.
  2. Tap Permissions → Notifications.
  3. Adjust your preference.
Chrome (Desktop)
  1. Click the padlock icon in the address bar.
  2. Select Site settings.
  3. Find Notifications and adjust your preference.