C ++ 11 + SDL2 + Windows:多线程程序在任何输入事件后挂起(C++11 + SDL2 + Windows: Multithreaded program hangs after any input event)
我正在使用C ++ 11,MinGW和Windows API进行屏幕捕获程序。 我正在尝试使用SDL2来观看我的屏幕捕获程序如何实时工作。
窗口打开很好,程序似乎运行良好,只要我只做移动鼠标光标。 但是如果我点击窗口,窗口外的菜单栏或按任意键,SDL窗口会冻结。
我已经为事件设置了一些日志记录来弄清楚发生了什么。 我从未按顺序接收除
SDL_WINDOW_FOCUS_GAINED
,SDL_TEXTEDITING
和SDL_WINDOWEVENT_SHOWN
之外的任何事件。 所有这些都是在一开始就收到的。我试图找到有关SDL事件处理的教程,因为这是我对问题根源的最佳猜测。 我发现只有基本的事件处理才能观察
SDL_QUIT
,基本的鼠标和键盘事件,以及一个似乎没有帮助的SDL_WINDOWEVENT
。 我没有深入了解事件的意义和处理它们的最佳实践。 这可能无关紧要,因为这可能不是问题的根源。 据我所知,SDL正在投入,因为还有其他线程正在运行。任何人都可以看到我的代码挂起的任何原因,并提供如何解决它的解释?
我的程序结构的快速解释是为了涵盖我省略的代码。
Captor
类启动并运行一个线程来获取屏幕截图以传递给Encoder
。Encoder
启动可变数量的线程,从Captor
接收屏幕截图,对屏幕截图进行编码,然后将编码传递给Screen
。 传递机制是SynchronousQueue<T>
类,它提供配对方法put(const T&)
和T get()
以允许生产者和消费者使用资源进行同步; 这些方法超时以允许系统响应以杀死消息。现在为源文件(希望没有太多的膨胀)。 虽然我很感激有关如何提高应用程序性能的任何意见,但我的重点是使程序具有响应性。
main.cpp中
#include "RTSC.hpp" int main(int argc, char** argv) { RTSC rtsc { (uint32_t) stoi(argv[1]), (uint32_t) stoi(argv[2]), (uint32_t) stoi(argv[3]), (uint32_t) stoi(argv[4]), (uint32_t) stoi(argv[5]), (uint32_t) stoi(argv[6]) }; while (rtsc.isRunning()) { SwitchToThread(); } return 0; }
RTSC.hpp
#ifndef RTSC_HPP #define RTSC_HPP #include "Captor.hpp" #include "Encoder.hpp" #include "Screen.hpp" #include <iostream> using namespace std; class RTSC { private: Captor *captor; Encoder *encoder; SynchronousQueue<uint8_t*> imageQueue {1}; SynchronousQueue<RegionList> regionQueue {1}; Screen *screen; public: RTSC( uint32_t width, uint32_t height, uint32_t maxRegionCount, uint32_t threadCount, uint32_t divisionsAlongThreadWidth, uint32_t divisionsAlongThreadHeight ) { captor = new Captor(width, height, imageQueue); encoder = new Encoder( width, height, maxRegionCount, threadCount, divisionsAlongThreadWidth, divisionsAlongThreadHeight, imageQueue, regionQueue ); screen = new Screen( width, height, width >> 1, height >> 1, regionQueue ); captor->start(); } ~RTSC() { delete screen; delete encoder; delete captor; } bool isRunning() const { return screen->isRunning(); } }; #endif
Screen.hpp
#ifndef SCREEN_HPP #define SCREEN_HPP #include <atomic> #include <SDL.h> #include <windows.h> #include "Region.hpp" #include "SynchronousQueue.hpp" using namespace std; class Screen { private: atomic_bool running {false}; HANDLE thread; SynchronousQueue<RegionList>* inputQueue; uint32_t inputHeight; uint32_t inputWidth; uint32_t screenHeight; uint32_t screenWidth; SDL_Renderer* renderer; SDL_Surface* surface; SDL_Texture* texture; SDL_Window* window; void run() { SDL_Event event; while (running) { while (SDL_PollEvent(&event)) { switch (event.type) { case SDL_QUIT: running = false; break; case SDL_WINDOWEVENT: switch (event.window.event) { case SDL_WINDOWEVENT_CLOSE: running = false; break; default: break; } } try { RegionList rl = inputQueue->get(); SDL_RenderClear(renderer); SDL_LockSurface(surface); SDL_FillRect(surface, nullptr, 0); for (uint32_t i = 0; i < rl.count; ++i) { Region &r = rl.regions[i]; SDL_Rect rect { (int) r.getX(), (int) r.getY(), (int) r.getWidth(), (int) r.getHeight() }; uint32_t color = (r.getRed() << 16) + (r.getGreen() << 8) + r.getBlue(); SDL_FillRect(surface, &rect, color); } SDL_UnlockSurface(surface); SDL_UpdateTexture( texture, nullptr, surface->pixels, surface->pitch ); SDL_RenderCopyEx( renderer, texture, nullptr, nullptr, 0, nullptr, SDL_FLIP_VERTICAL ); } catch (exception &e) {} SDL_RenderPresent(renderer); SwitchToThread(); } } static DWORD startThread(LPVOID self) { ((Screen*) self)->run(); return (DWORD) 0; } public: Screen( uint32_t inputWidth, uint32_t inputHeight, uint32_t windowWidth, uint32_t windowHeight, SynchronousQueue<RegionList> &inputQueue ): inputQueue {&inputQueue}, inputHeight {inputHeight} { SDL_Init(SDL_INIT_VIDEO); window = SDL_CreateWindow( "RTSC", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, windowWidth, windowHeight, SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE | SDL_WINDOW_INPUT_FOCUS | SDL_WINDOW_MOUSE_FOCUS ); renderer = SDL_CreateRenderer(window, -1, 0); surface = SDL_CreateRGBSurface( 0, inputWidth, inputHeight, 24, 0xFF << 16, 0xFF << 8, 0xFF, 0 ); texture = SDL_CreateTexture( renderer, surface->format->format, SDL_TEXTUREACCESS_STREAMING, inputWidth, inputHeight ); running = true; thread = CreateThread(nullptr, 0, startThread, this, 0, nullptr); } ~Screen() { running = false; WaitForSingleObject(thread, INFINITE); CloseHandle(thread); SDL_FreeSurface(surface); SDL_DestroyRenderer(renderer); SDL_DestroyWindow(window); SDL_Quit(); } bool isRunning() const { return running; } }; #endif
I am working on a screen capture program using C++11, MinGW, and the Windows API. I am trying to use SDL2 to watch how my screen capture program works in real time.
The window opens fine, and the program seems to run well so long as I do nothing more than move the mouse cursor. But iff I click in the window, its menu bar, outside the window, or press any keys, the SDL window freezes.
I have set up some logging for the events to figure out what is happening. I never receive any events other than
SDL_WINDOW_FOCUS_GAINED
,SDL_TEXTEDITING
, andSDL_WINDOWEVENT_SHOWN
in that order. All of these are received at the start.I have tried to find tutorials on SDL event handling since that's my best guess as to the source of the problem. I have found nothing more than basic event handling to watch for
SDL_QUIT
, basic mouse and keyboard events, and one onSDL_WINDOWEVENT
s that does not seem to help. I have found nothing in-depth on what the events mean and best practices for handling them. That may not matter, because that might not be the source of the problem. For all I know, SDL is throwing a fit because there are other threads running.Can anyone see any cause for this hanging in my code and provide an explanation as to how to fix it?
A quick explanation for the structure of my program is in order to cover the code I have omitted. The
Captor
class starts and runs a thread to grab a screenshot to pass to theEncoder
. TheEncoder
starts a variable number of threads that receive a screenshot from theCaptor
, encode the screenshot, then passes the encoding to theScreen
. The passing mechanism is theSynchronousQueue<T>
class that provides paired methodsput(const T&)
andT get()
to allow a producer and a consumer to synchronize using a resource; these methods time out to allow the the system to be responsive to kill messages.Now for the source files (hopefully without too much bloat). While I would appreciate any comments on how to improve the performance of the application, my focus is on making the program responsive.
main.cpp
#include "RTSC.hpp" int main(int argc, char** argv) { RTSC rtsc { (uint32_t) stoi(argv[1]), (uint32_t) stoi(argv[2]), (uint32_t) stoi(argv[3]), (uint32_t) stoi(argv[4]), (uint32_t) stoi(argv[5]), (uint32_t) stoi(argv[6]) }; while (rtsc.isRunning()) { SwitchToThread(); } return 0; }
RTSC.hpp
#ifndef RTSC_HPP #define RTSC_HPP #include "Captor.hpp" #include "Encoder.hpp" #include "Screen.hpp" #include <iostream> using namespace std; class RTSC { private: Captor *captor; Encoder *encoder; SynchronousQueue<uint8_t*> imageQueue {1}; SynchronousQueue<RegionList> regionQueue {1}; Screen *screen; public: RTSC( uint32_t width, uint32_t height, uint32_t maxRegionCount, uint32_t threadCount, uint32_t divisionsAlongThreadWidth, uint32_t divisionsAlongThreadHeight ) { captor = new Captor(width, height, imageQueue); encoder = new Encoder( width, height, maxRegionCount, threadCount, divisionsAlongThreadWidth, divisionsAlongThreadHeight, imageQueue, regionQueue ); screen = new Screen( width, height, width >> 1, height >> 1, regionQueue ); captor->start(); } ~RTSC() { delete screen; delete encoder; delete captor; } bool isRunning() const { return screen->isRunning(); } }; #endif
Screen.hpp
#ifndef SCREEN_HPP #define SCREEN_HPP #include <atomic> #include <SDL.h> #include <windows.h> #include "Region.hpp" #include "SynchronousQueue.hpp" using namespace std; class Screen { private: atomic_bool running {false}; HANDLE thread; SynchronousQueue<RegionList>* inputQueue; uint32_t inputHeight; uint32_t inputWidth; uint32_t screenHeight; uint32_t screenWidth; SDL_Renderer* renderer; SDL_Surface* surface; SDL_Texture* texture; SDL_Window* window; void run() { SDL_Event event; while (running) { while (SDL_PollEvent(&event)) { switch (event.type) { case SDL_QUIT: running = false; break; case SDL_WINDOWEVENT: switch (event.window.event) { case SDL_WINDOWEVENT_CLOSE: running = false; break; default: break; } } try { RegionList rl = inputQueue->get(); SDL_RenderClear(renderer); SDL_LockSurface(surface); SDL_FillRect(surface, nullptr, 0); for (uint32_t i = 0; i < rl.count; ++i) { Region &r = rl.regions[i]; SDL_Rect rect { (int) r.getX(), (int) r.getY(), (int) r.getWidth(), (int) r.getHeight() }; uint32_t color = (r.getRed() << 16) + (r.getGreen() << 8) + r.getBlue(); SDL_FillRect(surface, &rect, color); } SDL_UnlockSurface(surface); SDL_UpdateTexture( texture, nullptr, surface->pixels, surface->pitch ); SDL_RenderCopyEx( renderer, texture, nullptr, nullptr, 0, nullptr, SDL_FLIP_VERTICAL ); } catch (exception &e) {} SDL_RenderPresent(renderer); SwitchToThread(); } } static DWORD startThread(LPVOID self) { ((Screen*) self)->run(); return (DWORD) 0; } public: Screen( uint32_t inputWidth, uint32_t inputHeight, uint32_t windowWidth, uint32_t windowHeight, SynchronousQueue<RegionList> &inputQueue ): inputQueue {&inputQueue}, inputHeight {inputHeight} { SDL_Init(SDL_INIT_VIDEO); window = SDL_CreateWindow( "RTSC", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, windowWidth, windowHeight, SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE | SDL_WINDOW_INPUT_FOCUS | SDL_WINDOW_MOUSE_FOCUS ); renderer = SDL_CreateRenderer(window, -1, 0); surface = SDL_CreateRGBSurface( 0, inputWidth, inputHeight, 24, 0xFF << 16, 0xFF << 8, 0xFF, 0 ); texture = SDL_CreateTexture( renderer, surface->format->format, SDL_TEXTUREACCESS_STREAMING, inputWidth, inputHeight ); running = true; thread = CreateThread(nullptr, 0, startThread, this, 0, nullptr); } ~Screen() { running = false; WaitForSingleObject(thread, INFINITE); CloseHandle(thread); SDL_FreeSurface(surface); SDL_DestroyRenderer(renderer); SDL_DestroyWindow(window); SDL_Quit(); } bool isRunning() const { return running; } }; #endif
原文:https://stackoverflow.com/questions/22058447
满意答案
我想你可以使用它从你的相对路径获得一个绝对路径:
ServletContext ctx = ....; String absolutePath = ctx.getRealPath("/WEB-INF/" + relativePath);
Figured it out...
WTP uses the variable "${catalina.home}", not "${CATALINA_HOME}"...
相关问答
更多Eclipse WTP与Tomcat的干净和干净的工作目录之间的区别(difference between clean and clean working directory in Eclipse WTP with Tomcat)
使用eclipse wtp将web项目发布到tomcat之后缺少类(missing classes after publish web project into tomcat using eclipse wtp)
Eclipse WTP:如何在Tomcat上启用SSL?(Eclipse WTP: How do I enable SSL on Tomcat?)
从Eclipse WTP发布到服务器时如何排除Maven资源?(How do I exclude Maven resources when publishing from Eclipse WTP to a server?)
Eclipse的WTP转换输出(Eclipse's WTP translation output)
使用Eclipse的WTP Tomcat服务器调试servlet时,在web.xml中指定相对路径?(Specifying a relative path in web.xml when debugging a servlet with Eclipse's WTP Tomcat Server?)
如何在Eclipse中检查WTP的版本?(How to check version of WTP in Eclipse?)
WTP如何确定Tomcat版本(How does WTP determine the Tomcat version)
无法将servlet添加到Tomcat web.xml [关闭](Cannot add servlet to Tomcat web.xml [closed])
在哪里下载Eclipse WTP(Where to download Eclipse WTP)
相关文章
更多《编程之道 Java》(Program JAVA)[ISO]
A Great List of Windows Tools
摘抄---Multimedia Streaming on Microsoft Windows CE 3.0
WINDOWS渗透与提权总结(2)
Solr参数(DisMax Event Facet)
windows系统安装MongoDB
solr部署(windows)
Windows下 建立solr时 出现 问题解答(转 )
Windows Phone Emoji
Jordan 11 magic reversal
最新问答
更多获取MVC 4使用的DisplayMode后缀(Get the DisplayMode Suffix being used by MVC 4)
如何通过引用返回对象?(How is returning an object by reference possible?)
矩阵如何存储在内存中?(How are matrices stored in memory?)
每个请求的Java新会话?(Java New Session For Each Request?)
css:浮动div中重叠的标题h1(css: overlapping headlines h1 in floated divs)
无论图像如何,Caffe预测同一类(Caffe predicts same class regardless of image)
xcode语法颜色编码解释?(xcode syntax color coding explained?)
在Access 2010 Runtime中使用Office 2000校对工具(Use Office 2000 proofing tools in Access 2010 Runtime)
从单独的Web主机将图像传输到服务器上(Getting images onto server from separate web host)
从旧版本复制文件并保留它们(旧/新版本)(Copy a file from old revision and keep both of them (old / new revision))
Copyright ©2023 peixunduo.com All Rights Reserved.粤ICP备14003112号
本站部分内容来源于互联网,仅供学习和参考使用,请莫用于商业用途。如有侵犯你的版权,请联系我们(neng862121861#163.com),本站将尽快处理。谢谢合作!