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.
Related
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 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.
This question already has answers here:
MinGW 4.8.1 C++11 thread support
(2 answers)
Closed 7 years ago.
I have a problem including the thread library. The following code:
#include <string>
#include <iostream>
#include <thread>
using namespace std;
//The function we want to make the thread run.
void task1(string msg)
{
cout << "task1 says: " << msg;
}
int main()
{
// Constructs the new thread and runs it. Does not block execution.
thread t1(task1, "Hello");
//Makes the main thread wait for the new thread to finish execution, therefore blocks its own execution.
t1.join();
}
Produces these errors:
The code is taken from the answer to another stackoverflow question. I am fairly new to codeblocks and C++ so please explain to me what I am doing wrong.
You probably have not set proper flags for compiler (so that it uses c++11). Way of doing it in codeblocks
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.
This is test example:
(1). simple program doing endless loop:
#include <iostream>
using namespace std;
int main() {
int counter = 0;
while (1) cout << ++counter << ": endless loop..." <<endl;
}
(2). another program that launches above example through system() command:
#include <iostream>
#include <windows.h>
using namespace std;
int main() {
system("endless_loop.exe");
cout << "back to main program" << endl;
}
When doing Ctrl+Break on this program text back to main program doesn't show.
How to restrict this key combination to inside process and return execution pointer back to main app ?
Another thing is that I don't always have control over source code of inside program, so I can't change things there.
Add this::
#include <signal.h>
...
signal (SIGINT, SIG_IGN);
After the signal() call, the program ignores Ctrl-Break. On Linux, ignoring signals propagates to child processes through fork()/exec().
I would expect Windows to reset the default signal handling on exec() due to the way the O/S + runtime library work. So if you want the child to ignore Break, add the code above to it too.