I'm trying to run an SFML window on a separate thread from main(). Calling sf::Window::close doesn't cause any immediate problems, however at the end of main(), possibly when the UI object is destructed, a segmentation fault error occurs. No segmentation fault occurs if sf::Window::close isn't called.
I'm running a fully updated Debian 10 install.
#include <thread>
#include <SFML/Graphics.hpp>
int main() {
sf::Window window(sf::VideoMode(500,500), "Test");
std::thread th(&sf::Window::close, &window);
th.join();
}
I found the problem. You have to deactivate the window before closing in another thread, like so. I missed this in the documentation initially.
#include <thread>
#include <SFML/Graphics.hpp>
int main() {
sf::Window window(sf::VideoMode(500,500), "Test");
window.setActive(false);
std::thread th(&sf::Window::close, &window);
th.join();
}
Related
This question already has an answer here:
SFML fails in multithreading
(1 answer)
Closed 1 year ago.
I am trying to create a separate thread while using the SFML game library. This is a very simplified example.
I'm using WSL and the libsfml-dev library. My issue is that it seems like I cannot perform certain actions using the SFML library on threads other then my main thread. For example, in the code below, I get an error if I click escape. What's supposed to happen is the program simply exits as the loop conditions fail.
If you want to run the code yourself...
to grab the library: apt-get install libsfml-dev
g++ compiler arguments: g++ test.cpp -pthread -lsfml-graphics -lsfml-window -lsfml-system
#include <iostream>
#include <stdio.h>
#include <pthread.h>
#include <SFML/Graphics.hpp>
#include <SFML/System.hpp>
// Create window object
sf::RenderWindow window(sf::VideoMode(800, 800), "");
using namespace std;
void *func(void *threadid) {
// Show thread was created
cout << "New thread was ran." << endl;
while (window.isOpen()) {
// This action kills the program and not in a nice way
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Escape)) {
window.close();
}
}
pthread_exit(NULL);
}
int main() {
// Create new thread
pthread_t threads[1];
int val;
val = pthread_create(&threads[0], NULL, func, (void *)1);
cout << "Main thread was ran." << endl;
// This is here so that the program doesn't exit
while (window.isOpen()) {}
return 0;
}
Error message
It is not uncommon to have to do all GUI updates from the main thread. It is likely that SFML is not even thread-safe. You need to communicate from your other threads to the main thread and let them do things like window.close().
If I modify your example and simply return from the second thread instead of calling window.close(), it does not crash.
im new to sfml and c++.and I have a project that uses the sfml library's to draw the graphics but when I add an additional thread to my program it fails to execute the code inside the thread. this is my code:(please help me!)
#include <SFML\Graphics.hpp>
#include <SFML\window.hpp>
#include <SFML\system.hpp>
#include <iostream>
#include <thread>
#include <chrono>
using namespace std;
int h(sf::RenderWindow* win){
//do something
win->close();
this_thread::sleep_for(chrono::milliseconds(10));
return 0;
}
int main(){
sf::RenderWindow window(sf::VideoMode(800,600),"My window");
thread t1(h,&window);
_sleep(10000000);
t1.join();
return 0;
}
http://www.sfml-dev.org/tutorials/2.0/graphics-draw.php#drawing-from-threads
SFML supports multi-threaded drawing, and you don't even have to do
anything to make it work. The only thing to remember is to deactivate
a window before using it in another thread; that's because a window
(more precisely its OpenGL context) cannot be active in multiple
threads at the same time.
call window.setActive(false); in your main(), before you pass it off to the thread.
And remember that you must handle events in the GUI thread (the main thread) for maximum portability.
I'm trying to debug (GDB) my application developped with Cygwin under Windows.
When I debug this, I got "Signal received: ? (Unknown signal)" when the thread is created and the program stop.
#include <iostream>
#include <thread>
using namespace std;
void ConnectionTimer()
{
}
int main(int argc, char** argv) {
cout<<"Before thread creation"<<endl;
std::thread t( ConnectionTimer);
cout<<"After thread creation"<<endl;
t.join();
cout<<"After join"<<endl;
return 0;
}
The debugger stop at the line
status = NtCreateMutant (&mtx, MUTEX_ALL_ACCESS, &attr, bInitialOwner);in kernel32.cc.
It work as expected in run mode but crash in debug.
Result in run mode :
Before thread creation
After thread creation
After join
Result in debug mode (before crash):
Before thread creation
Any ideas what i'm missing ?
EDIT
If I comment thread related lines, it work properly.
Call Stack
Signal caught which cause crash
Discard
Configuration :
Cygwin 3.1.4-1 on W10 under GDB 8.2.1-1, compiled with g++ (GCC) 9.2.0-3
I found the reason of the crash.
My antivirus (Trend) was blocking the program, I had to create an exception for the exe and everything is now working fine.
I am trying to play a song in a background thread of my GUI application so that the song doesn't block the GUI thread. Is there a simple way to do this with either std::thread or SFML Threads?
I have tried using std::thread for this, but it still blocks the GUI thread when I call my_thread.join().
Here is an example of what I want to do:
#include <thread>
#include <SFML/Audio.hpp>
#include <unistd.h>
#include <iostream>
void func() {
sf::Music music;
music.openFromFile("mysong.wav");
music.play();
// if I don't have usleep here the function exits immediately
// why is that exactly???
usleep(100000000);
}
int main() {
std::thread my_thread(func);
my_thread.join();
// this is where I would process events/build windows in GUI
while(1)
std::cout << "here"; // <--- Want this to run while song plays
}
in SFML you need to have a valid sf::Sound or sf::Music for music to play, when that variable gets destroyed you will no longer have a valid reference to that object a possible solution for the code you posted would be something like this:
#include <SFML/Audio.hpp>
#include <unistd.h>
#include <iostream>
class CAudio
{
sf::Music music;
public:
void func()
{
music.openFromFile("mysong.wav");
music.play();
}
sf::Status getStatus()
{
return music.getStatus();
}
}
int main() {
CAudio my_music;
my_music.func();
// http://www.sfml-dev.org/documentation/2.0/SoundSource_8hpp_source.php
while(my_music.getStatus() == sf::Status::Playing)
{
std::cout << "here"; // <--- Want this to run while song plays
}
}
Also, always use brackets, regardless if its a 1 line statement always use brackets, I know its allowed but it will make your life easier when you troubleshoot later on.
im new to sfml and c++.and I have a project that uses the sfml library's to draw the graphics but when I add an additional thread to my program it fails to execute the code inside the thread. this is my code:(please help me!)
#include <SFML\Graphics.hpp>
#include <SFML\window.hpp>
#include <SFML\system.hpp>
#include <iostream>
#include <thread>
#include <chrono>
using namespace std;
int h(sf::RenderWindow* win){
//do something
win->close();
this_thread::sleep_for(chrono::milliseconds(10));
return 0;
}
int main(){
sf::RenderWindow window(sf::VideoMode(800,600),"My window");
thread t1(h,&window);
_sleep(10000000);
t1.join();
return 0;
}
http://www.sfml-dev.org/tutorials/2.0/graphics-draw.php#drawing-from-threads
SFML supports multi-threaded drawing, and you don't even have to do
anything to make it work. The only thing to remember is to deactivate
a window before using it in another thread; that's because a window
(more precisely its OpenGL context) cannot be active in multiple
threads at the same time.
call window.setActive(false); in your main(), before you pass it off to the thread.
And remember that you must handle events in the GUI thread (the main thread) for maximum portability.