how use multithread inside a class?

Pages: 123
i have the 'image' class.inside the class i have these function:
void DrawLine3D(Position3D Origin, Position3D Destination, COLORREF LineColor=RGB(255,255,255), HDC HDCTexture=0, int StartTextureX=0, int StartTextureY=0, bool Refresh=true)
inside these function i use some class variables.
my question is: how can i add these function on multithread code?
Last edited on
There are so many different answers to your question that there's no way to answer it.

Broadly speaking, parallelizing a piece of code involves identifying sections that are amenable to parallelism, perhaps modifying the code slightly to make it more amenable, and then restructuring the code so that those sections execute in parallel rather than sequentially.
I'm sorry to say, if you've never done it then chances are you're going to do it wrong (i.e. you're not going to improve performance, or you're going to introduce subtle bugs, or both), because parallel programming is one of the hardest things to get right. I'd suggest you leave this for a while and start playing around with threads in a test project, and then come back to this once you know at least the basics.
Last edited on
The problem of multithreading is the synchronization. Starting/stopping a thread is also rather slow. Thus you can easily make your code run slower with multithreading.

You usually need an infrastructure (like queue, mutex, condition_variable) for a thread. And you need something that could run parallel, i.e. you don't need the result instantly. For instance you might want to do the calculation from 3-D to 2-D within a thread. So that it doesn't need to be calculated when you draw it. But that needs some preparation and depends on what you want to achieve.
ok.. i did a simple code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#include <iostream>
#include <thread>

struct test
{
    struct Person
    {
        int Age = 0;
        std::string Name = "";
        int *H;
    };

    void f(Person *Pessoa)
    {
        std::cout <<"Name: " << Pessoa->Name << "\n";
        std::cout << "Age: " << Pessoa->Age << "\n";
        std::cout << "H: " << *Pessoa->H << "\n";
    }
    void te()
    {
        std::thread th[100];
        Person Pessoa;
        Pessoa.Age=39;
        Pessoa.Name ="Joaquim";

        Pessoa.H = new int(1000);
        for (int i = 0; i < 100; i += 1)
        {
            th[i] = std::thread(this->f, &Pessoa);//erros
            th[i].join();

        }
        delete  Pessoa.H;

    }
};
test a;
int main()
{
    a.te();
    std::cout << "Todas thread terminaram\n";
    return 0;
}

these code is a simple code and the error is here:
th[i] = std::thread(this->f, &Pessoa);//erros
so heres the question: how use the std::thread() inside a class?
i know the error is on 1st parameter.
i tested the code from a function and a structure until a class.
my problem is here.
Note: these is for i update my image class. and maybe win more speed
finally i fix it.. in a function we do:
std::thread(FunctionName, Parameter);
honestly i don't know if i can use more parameters.

in a classe we do:
std::thread(&ClassName::FunctionName, ClassPointer, Parameter);
like i said: i don't know if i can use more parameters.
now see the Pixel structure:
1
2
3
struct Pixel
    {
        image *img;

when i use it:
1
2
3
4
5
6
Pixel *pix;
            pix->color = LineColor;
            pix->X =X;
            pix->Y=Y;
            pix->Z=Z;
            pix->img = new image(*this);

how can i add the class object pointer?
i tested the code and i get the 'X' and, maybe, the others.
but seems that i get the 'img' wrong :(
what i'm doing wrong?
 
std::thread([this, &Pessoa](){ this->f(&Pessoa); });


Note that creating an std::thread and then immediately join()ing it is pointless, as it forces the work to become serialized, as if no threads were involved.
You want to do this:
1
2
3
4
for (auto &t : threads)
    t = std::thread(/*...*/);
for (auto &t : threads)
    t.join();

not this:
1
2
3
4
for (auto &t : threads){
    t = std::thread(/*...*/);
    t.join();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#include <iostream>
#include <string>
#include <vector>
#include <future>
#include <syncstream>

struct person
{
    std::string name ;
    int age = 0 ;
    int phone[4] {} ;

    std::ostream& print( std::ostream& stm ) const
    {
        stm << "person{ " << name << ", " << age << ", [" ;
        for( int p : phone ) if( p > 0 ) stm << p << ' ' ;
        return stm << "]}\n" ;
    }
};

void fun()
{
    const person persons[] { { "abc", 21, {2,3,4} }, { "def", 33, {5} }, { "ghi", 61, {6,7,6,9} } } ;

    std::vector< std::future< std::ostream& > > futures ;

    std::osyncstream stm { std::cout } ;
    for( const person& p : persons )
        futures.push_back( std::async( std::launch::async, &person::print, std::ref(p), std::ref(stm) ) ) ;
    //                 async call of member function person::print on person object p using stream stm by reference

    for( auto& f : futures ) f.get() ; // wait for the async operations to complete
    stm << "*** done ***\n" ;
}

int main()
{
    fun() ;
}


Caveat: std::osyncstream appears to be buggy in the GNU implementation.
Last edited on
i miss something :(
i must use:
th[i] = std::thread(&image::DrawPixel,*this, pix);
'*' on 'this'.
i have another bug on code. but i need fix 1 more thing:
1
2
3
4
5
6
7
//inside the 'image' class:
Pixel *pix;
            pix->color = LineColor;
            pix->X =X;
            pix->Y=Y;
            pix->Z=Z;
            pix->img = (image*)this;

'pix->img = (image*)this;' is these the right way for get the image instance pointer?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include <thread>

struct image ;

struct pixels
{
    image* ptr_image = nullptr ;
};

struct image
{
    void foo( pixels& pix )
    {
        pix.ptr_image = this ; // fine
    }

    void cfoo( pixels& pix ) const
    {
        // pix.ptr_image = this ; // *** error *** : attempted implicit conversion from const image* to image*
        pix.ptr_image = (image*)this ; // *** warning *** : not const-correct; potential UB
    }

    void async( pixels& pix )
    {
        std::thread( &image::foo, this, std::ref(pix) ).detach() ; // fine
        std::thread( &image::foo, std::ref(*this), std::ref(pix) ).detach() ; // fine

        std::thread( &image::foo, *this, std::ref(pix) ).detach() ; // *** warning *** : thread operates on a copy of the image object
        // std::thread( &image::foo, std::ref(*this), pix ).detach() ; // *** error *** : thread gets a copy of the pixel object; it is const
    }
};
JLBorges i'm testing it... but i get errors :(
even with:
std::thread( &image::foo, this, std::ref(pix) ).detach() ;
i can enter on function:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
void DrawPixel(Pixel *Pix )
    {
        cout << "hey";
        //return;
        //For every steps we calculate the perspective:
        //Avoiding division by zero:
        float EyeDistance = 500;// doing these i avoid the black\empty vertical lines
        const float d = EyeDistance+Pix->Z; // Note that Z==0 is irrelevant here
        const float Perspective = (d != 0) ? (EyeDistance/d) : 0;

        //The 3D to 2D convertion(i use 300 of eye distance, but we can change it):
        int PosX = Pix->X*Perspective;
        int PosY = Pix->Y*Perspective;


        //Draw the pixel on valid positions:
        if(Pix->Z>=0 && PosX<Pix->img->Width && PosX>=0 && PosY<Pix->img->Height && PosY>=0)
        {
            size_t pixelOffset = PosY * Pix->img->scanlineSize + PosX * Pix->img->pixelSize;
            int PosR = pixelOffset+2;
            int PosG = pixelOffset+1;
            int PosB = pixelOffset+0;

            Pix->img->Pixels[PosR]=GetRValue(Pix->color);
            Pix->img->Pixels[PosG]=GetGValue(Pix->color);
            Pix->img->Pixels[PosB]=GetBValue(Pix->color);
        }
    }

the 'cout' is done with these line:
1
2
 cout << "hey";
        //return; 


1
2
3
4
5
6
7
8
9
10
11
12
13
14
int i=0;
        Pixel *pix;
        std::thread th[(int)LineDistance] ;
        do
        {


            pix->color = LineColor;
            pix->X =X;
            pix->Y=Y;
            pix->Z=Z;
            pix->img =this;
            th[i]= std::thread(&image::DrawPixel,*this, pix);
            th[i].join();

when the line:
1
2
float EyeDistance = 500;// doing these i avoid the black\empty vertical lines
        const float d = EyeDistance+Pix->Z;

is executed, i get and error on exe: "Process returned -1073741819 (0xC0000005) execution time : 0.785 s
Press any key to continue."
is these line correct?
pix->img =this;
or is realy wrong these line:
th[i]=std::thread(&image::DrawPixel,*this, pix);
i tried the others samples, without success :(
> Process returned -1073741819 (0xC0000005)

0xC0000005 is the Windows error code for an access violation (EXCEPTION_ACCESS_VIOLATION; attempted invalid access to a memory location).

Run it under the debugger and discover where (and in which thread) you get the access violation. And then try to reason out why this happens.
This looks rather confusing.

is these line correct?
pix->img =this;
Sure, but it seems to make no sense?

or is realy wrong these line:
th[i]=std::thread(&image::DrawPixel,*this, pix);
That line provides a copy of the this object. If DrawPixel(...) is a member function (and not a free function) you need to provide the this pointer directly:
th[i]=std::thread(&image::DrawPixel,this, pix); // No *

1
2
            th[i]= std::thread(&image::DrawPixel,*this, pix);
            th[i].join();
This is only a over complicated function call. Move the joins outside the this loop.
> std::thread th[(int)LineDistance] ;
Be careful about choosing the granularity of threading.
- You need to do a lot more work per thread (than setting a single pixel), to justify the overhead of creating threads.
- Creating more threads than you have physical cores will thrash the scheduler.

Consider an example where each thread is given a quarter of the bitmap to work on.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
#include <iostream>
#include <chrono>
#include <thread>
#include <cstring>

#ifndef IMAGE_SIZE
#define IMAGE_SIZE  1000
#endif

void sequential_by_rows(int pixels[IMAGE_SIZE][IMAGE_SIZE], int fx, int tx, int fy, int ty, int value) {
    for ( int y = fy ; y < ty ; y++ ) {
        for ( int x = fx ; x < tx ; x++ ) {
            pixels[y][x] = value;
        }
    }
}

// Filling an array in column order is less cache friendly.
void sequential_by_cols(int pixels[IMAGE_SIZE][IMAGE_SIZE], int fx, int tx, int fy, int ty, int value) {
    for ( int x = fx ; x < tx ; x++ ) {
        for ( int y = fy ; y < ty ; y++ ) {
            pixels[y][x] = value;
        }
    }
}

int main ()
{
    static int pixels[IMAGE_SIZE][IMAGE_SIZE];
    memset(pixels, 0, sizeof(pixels));
    
    {
        auto start = std::chrono::high_resolution_clock::now();
        auto stop = std::chrono::high_resolution_clock::now();
        auto duration = std::chrono::duration_cast<std::chrono::microseconds> (stop - start);
        std::cout << "Empty took " << duration.count() << std::endl;
    }
    
    {
        auto start = std::chrono::high_resolution_clock::now();
        sequential_by_rows(pixels, 0, IMAGE_SIZE, 0, IMAGE_SIZE, 42);
        auto stop = std::chrono::high_resolution_clock::now();
        auto duration = std::chrono::duration_cast<std::chrono::microseconds> (stop - start);
        std::cout << "sequential_by_rows took " << duration.count() << std::endl;
    }
    
    {
        auto start = std::chrono::high_resolution_clock::now();
        sequential_by_cols(pixels, 0, IMAGE_SIZE, 0, IMAGE_SIZE, 42);
        auto stop = std::chrono::high_resolution_clock::now();
        auto duration = std::chrono::duration_cast<std::chrono::microseconds> (stop - start);
        std::cout << "sequential_by_cols took " << duration.count() << std::endl;
    }
    
    {
        auto start = std::chrono::high_resolution_clock::now();
        std::thread t1(sequential_by_rows, pixels, 0, IMAGE_SIZE, 0, IMAGE_SIZE, 42);
        t1.join();
        auto stop = std::chrono::high_resolution_clock::now();
        auto duration = std::chrono::duration_cast<std::chrono::microseconds> (stop - start);
        std::cout << "sequential_by_rows in 1 thread took " << duration.count() << std::endl;
    }
    
    {
        int half = IMAGE_SIZE / 2;
        auto start = std::chrono::high_resolution_clock::now();
        std::thread t1(sequential_by_rows, pixels, 0, half,             0, half, 42);          // TL
        std::thread t2(sequential_by_rows, pixels, 0, half,             half, IMAGE_SIZE, 42); // BL
        std::thread t3(sequential_by_rows, pixels, half, IMAGE_SIZE,    0, half, 42);          // TR
        std::thread t4(sequential_by_rows, pixels, half, IMAGE_SIZE,    half, IMAGE_SIZE, 42); // BR
        t1.join();
        t2.join();
        t3.join();
        t4.join();
        auto stop = std::chrono::high_resolution_clock::now();
        auto duration = std::chrono::duration_cast<std::chrono::microseconds> (stop - start);
        std::cout << "sequential_by_rows in 4 thread took " << duration.count() << std::endl;
    }
    
    {
        auto start = std::chrono::high_resolution_clock::now();
        std::thread t1(sequential_by_cols, pixels, 0, IMAGE_SIZE, 0, IMAGE_SIZE, 42);
        t1.join();
        auto stop = std::chrono::high_resolution_clock::now();
        auto duration = std::chrono::duration_cast<std::chrono::microseconds> (stop - start);
        std::cout << "sequential_by_cols in 1 thread took " << duration.count() << std::endl;
    }
    
    {
        int half = IMAGE_SIZE / 2;
        auto start = std::chrono::high_resolution_clock::now();
        std::thread t1(sequential_by_cols, pixels, 0, half,             0, half, 42);          // TL
        std::thread t2(sequential_by_cols, pixels, 0, half,             half, IMAGE_SIZE, 42); // BL
        std::thread t3(sequential_by_cols, pixels, half, IMAGE_SIZE,    0, half, 42);          // TR
        std::thread t4(sequential_by_cols, pixels, half, IMAGE_SIZE,    half, IMAGE_SIZE, 42); // BR
        t1.join();
        t2.join();
        t3.join();
        t4.join();
        auto stop = std::chrono::high_resolution_clock::now();
        auto duration = std::chrono::duration_cast<std::chrono::microseconds> (stop - start);
        std::cout << "sequential_by_cols in 4 thread took " << duration.count() << std::endl;
    }

    return 0;
}


Test results, with and without optimisation, for two different image sizes.

$ g++ -DIMAGE_SIZE=1000 foo.cpp -pthread
$ ./a.out 
Empty took 0
sequential_by_rows took 4505
sequential_by_cols took 6177
sequential_by_rows in 1 thread took 5338
sequential_by_rows in 4 thread took 1282
sequential_by_cols in 1 thread took 9748
sequential_by_cols in 4 thread took 1154
$ g++ -DIMAGE_SIZE=1000 -O2 foo.cpp -pthread
$ ./a.out 
Empty took 0
sequential_by_rows took 671
sequential_by_cols took 7450
sequential_by_rows in 1 thread took 893
sequential_by_rows in 4 thread took 347
sequential_by_cols in 1 thread took 12120
sequential_by_cols in 4 thread took 545
$ g++ -DIMAGE_SIZE=2000 foo.cpp -pthread
$ ./a.out 
Empty took 0
sequential_by_rows took 10912
sequential_by_cols took 32993
sequential_by_rows in 1 thread took 17515
sequential_by_rows in 4 thread took 3001
sequential_by_cols in 1 thread took 30843
sequential_by_cols in 4 thread took 7556
$ g++ -DIMAGE_SIZE=2000 -O2 foo.cpp -pthread
$ ./a.out 
Empty took 0
sequential_by_rows took 2355
sequential_by_cols took 28486
sequential_by_rows in 1 thread took 3125
sequential_by_rows in 4 thread took 1796
sequential_by_cols in 1 thread took 37073
sequential_by_cols in 4 thread took 7897
finally i get the code working(if i can't add the multithread code to my image class, i can add my image class on my multithread code ;) )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
#include <iostream>
#include <thread>
#include <windows.h>
#include <math.h>

using namespace std;
class image
{
public:
    int ImageWidth = 0;
    int ImageHeight = 0;
    HDC ImageHDC = NULL;
    HBITMAP ImageBitmap;
    HBITMAP oldBit;
    BITMAP bmp;
    BITMAPINFO info;
    size_t pixelSize;
    size_t scanlineSize;
    size_t bitmapSize;
    void* p;
    LPBYTE Pixels;


    void Clear(COLORREF BackColor = RGB(0,0,0))
    {
        RECT rec{0,0,ImageWidth,ImageHeight};
        HBRUSH HB = CreateSolidBrush(BackColor);
        FillRect(ImageHDC,&rec,HB);
        DeleteObject(HB);
    }

    image(int Width, int Height, COLORREF BackColor=RGB(0,0,0))
    {
        ImageHDC = CreateCompatibleDC(NULL);
        ImageWidth = Width;
        ImageHeight =Height;

        ZeroMemory (&info, sizeof (BITMAPINFO));
        info.bmiHeader.biSize = sizeof(info.bmiHeader);
        info.bmiHeader.biWidth = ImageWidth;
        // pay attention to the sign, you most likely want a
        // top-down pixel array as it's easier to use
        info.bmiHeader.biHeight = -ImageHeight;
        info.bmiHeader.biPlanes = 1;
        info.bmiHeader.biBitCount = 32;
        info.bmiHeader.biCompression = BI_RGB;
        info.bmiHeader.biSizeImage = 0;
        info.bmiHeader.biXPelsPerMeter = 0;
        info.bmiHeader.biYPelsPerMeter = 0;
        info.bmiHeader.biClrUsed = 0;
        info.bmiHeader.biClrImportant = 0;

        // the following calculations work for 16/24/32 bits bitmaps
        // but assume a byte pixel array


        ImageBitmap = CreateDIBSection(ImageHDC, &info, DIB_RGB_COLORS, (LPVOID*)&Pixels, 0, 0);
        if(ImageBitmap ==NULL) cout << "no HBITMAP";
        if(SelectObject(ImageHDC, ImageBitmap)==NULL) cout << "error";
        pixelSize = info.bmiHeader.biBitCount / 8;
        // the + 3 ) & ~3 part is there to ensure that each
        // scan line is 4 byte aligned
        scanlineSize = (pixelSize * info.bmiHeader.biWidth + 3) & ~3;
        bitmapSize = bmp.bmHeight * scanlineSize;
        Clear(BackColor);
    }



    void NewSetPixel(HDC DestinationHDC, int X, int Y, BYTE RedColor, BYTE GreenColor, BYTE BlueColor)
    {
        size_t pixelOffset = Y *scanlineSize + X *pixelSize;
        Pixels[pixelOffset+2]=RedColor;
        Pixels[pixelOffset+1]=GreenColor;
        Pixels[pixelOffset+0]=BlueColor;
    }

    void DrawLine( float X0, float Y0, float Z0, float X1, float Y1, float Z1, COLORREF LineColor)
    {
        //Getting Line Distance(float results):
        float DX = abs(X1 - X0);
        float DY = abs(Y1 - Y0);
        float DZ = abs(Z1 - Z0);
        float LineDistance =sqrt((DX * DX) + (DY * DY) + (DZ * DZ));


        //Getting the Steps incrementation(float results):
        float XSteps = DX/LineDistance;
        float YSteps = DY/LineDistance;
        float ZSteps = DZ/LineDistance;

        //Draw Line using the Steps\ Incrementation:
        float X = X0;
        float Y = Y0;
        float Z = Z0;
        BYTE R = GetRValue(LineColor);
        BYTE G = GetGValue(LineColor);
        BYTE B = GetBValue(LineColor);
        std::thread th[(int)LineDistance+1];
        for(int i =0; i <LineDistance; i++)
        {
            //For every steps we calculate the perspective:
            float EyeDistance = 500;
            //Avoiding division by zero:
            if(Z==0) Z=1;
            float Perspective = EyeDistance/(EyeDistance+Z);

            //The 3D to 2D convertion(i use 300 of eye distance, but we can change it):

            int PosX = trunc(X*Perspective);
            int PosY = trunc(Y*Perspective);
            if(Z>=0 && PosX<ImageWidth && PosX>=0 && PosY<ImageHeight && PosY>=0)
            {
                th[i] = std::thread(&image::NewSetPixel,this,ImageHDC, PosX,PosY,R,G,B);//erros
                th[i].join();
                //NewSetPixel(ImageHDC, PosX,PosY,R,G,B);
            }

            //Increment steps(integer results):
            X+=XSteps;
            Y+=YSteps;
            Z+=ZSteps;
        }
    }

    void DrawRectangle(float PosX, float PosY, float PosZ, float Width, float Height, float Depth, COLORREF Color = RGB(255,0,0), bool Filled = false)
    {
        DrawLine( PosX, PosY, PosZ,PosX + Width, PosY, PosZ + Depth, Color);
        DrawLine( PosX, PosY, PosZ, PosX, PosY + Height, PosZ, Color);
        DrawLine( PosX + Width, PosY, PosZ + Depth, PosX + Width, PosY+Height, PosZ + Depth, Color);
        DrawLine( PosX, PosY + Height, PosZ, PosX + Width, PosY + Height, PosZ + Depth, Color);
        if(Filled==true)
        {
            for(int i = 0; i<Height; i++)
                DrawLine( PosX, PosY + i, PosZ,PosX + Width, PosY +i, PosZ + Depth, Color);

        }
    }

    ~image()
    {
        SelectObject(ImageHDC, oldBit);
        DeleteObject(ImageBitmap);
        DeleteDC(ImageHDC);
    }

};

image img(200,200);

int main()
{
    img.DrawRectangle(0,100,0, 100,100,500, RGB(255,0,0),true);
    BitBlt(GetWindowDC(GetConsoleWindow()),10,100,img.ImageWidth,img.ImageHeight,img.ImageHDC,0,0,SRCCOPY);

    return 0;
}

these code works. but why is much more slower than without multithread?
Lines 114-115.
I wrote:
Note that creating an std::thread and then immediately join()ing it is pointless, as it forces the work to become serialized, as if no threads were involved.
coder777 wrote:
This is only a over complicated function call. Move the joins outside the this loop.
seems that i miss that... but i get an run error:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
std::thread th[(int)LineDistance];
        int PosX;
        int PosY;
        for(int i=0; i<LineDistance; i++)
            th[i] = std::thread(&image::NewSetPixel,this,ImageHDC, PosX,PosY,R,G,B);//erros
        for(int i =0; i <LineDistance; i++)
        {
            //For every steps we calculate the perspective:
            float EyeDistance = 500;
            //Avoiding division by zero:
            if(Z==0) Z=1;
            float Perspective = EyeDistance/(EyeDistance+Z);

            //The 3D to 2D convertion(i use 300 of eye distance, but we can change it):

            PosX = trunc(X*Perspective);
            PosY = trunc(Y*Perspective);
            if(Z>=0 && PosX<ImageWidth && PosX>=0 && PosY<ImageHeight && PosY>=0)
            {

                th[i].join();
                //NewSetPixel(ImageHDC, PosX,PosY,R,G,B);
            }

            //Increment steps(integer results):
            X+=XSteps;
            Y+=YSteps;
            Z+=ZSteps;
        }

"Process returned -1073741819 (0xC0000005) execution time : 1.194 s
Press any key to continue."
You're probably doing things in the wrong order. I could look into things more closely, but there's no point. The function you're executing in parallel does practically nothing; it's never going to run faster like that no matter how you reorder things. You need to step back and redesign, this is unworkable.
helios: to be honest i'm not follow you. what i understand is that i'm doing things on wrong way\order.
how can i redesign if i think it's the 'right design'?
i don't see another order\algorithm :(
i can share the entire DrawLine() function and comment it for see the steps. is what i can do. even so i don't know how can i otimizate the function :(
these code works. but why is much more slower than without multithread?
Of course it is. To gain speed with threads is not simple. Why do you think that NewSetPixel(...) (which just sets some byte values into a byte array) is a good idea to put into a thread? You may start hundreds maybe thousands threads for such a simple task.

seems that i miss that... but i get an run error:
Oh dear:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
std::thread th[(int)LineDistance];
        int PosX;
        int PosY;
        for(int i =0; i <LineDistance; i++)
        {
            //For every steps we calculate the perspective:
            float EyeDistance = 500;
            //Avoiding division by zero:
            if(Z==0) Z=1; // This does not avoid division by zero!
            float Perspective = EyeDistance/(EyeDistance+Z);

            //The 3D to 2D convertion(i use 300 of eye distance, but we can change it):

            PosX = trunc(X*Perspective);
            PosY = trunc(Y*Perspective);
            if(Z>=0 && PosX<ImageWidth && PosX>=0 && PosY<ImageHeight && PosY>=0)
            {

            th[i] = std::thread(&image::NewSetPixel,this,ImageHDC, PosX,PosY,R,G,B);//erros
                //NewSetPixel(ImageHDC, PosX,PosY,R,G,B);
            }

            //Increment steps(integer results):
            X+=XSteps;
            Y+=YSteps;
            Z+=ZSteps;
        }
        for(int i=0; i<LineDistance; i++)
                th[i].join();
Even this is unlikely to speed up anything. Rather use DrawLine(...) in a thead. Not that I expect a much better result. As I already mentioned: Starting/stopping a thread is a costly action.
if you've never done it then chances are you're going to do it wrong (i.e. you're not going to improve performance, or you're going to introduce subtle bugs, or both), because parallel programming is one of the hardest things to get right.
Pages: 123