Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
__拧入Embarcadero c++;10.1不创建特定于线程的变量 在一个NavaCabro C++ 10.1程序中,我使用“新建”创建线程的多个实例。在每个实例中,我都需要包含指针和整数的线程特定变量_C++_Multithreading_Declspec - Fatal编程技术网

__拧入Embarcadero c++;10.1不创建特定于线程的变量 在一个NavaCabro C++ 10.1程序中,我使用“新建”创建线程的多个实例。在每个实例中,我都需要包含指针和整数的线程特定变量

__拧入Embarcadero c++;10.1不创建特定于线程的变量 在一个NavaCabro C++ 10.1程序中,我使用“新建”创建线程的多个实例。在每个实例中,我都需要包含指针和整数的线程特定变量,c++,multithreading,declspec,C++,Multithreading,Declspec,我尝试了两种不同的声明: static TProgram_Control __thread * ptrPC_local; static int __thread i_local; 及 我尝试了使用和不使用“static”修饰符。我看到两个线程的行为表明,每个线程都在为这些变量的值相互碰撞 我在每个线程中添加了代码来打印线程ID和两个变量的地址 PrintItem("TProg_Control_Thread(" + String(MyPCNo) + "): &ptrPC_local 0x

我尝试了两种不同的声明:

static TProgram_Control __thread * ptrPC_local;
static int __thread i_local;

我尝试了使用和不使用“static”修饰符。我看到两个线程的行为表明,每个线程都在为这些变量的值相互碰撞

我在每个线程中添加了代码来打印线程ID和两个变量的地址

PrintItem("TProg_Control_Thread(" + String(MyPCNo) + "): &ptrPC_local 0x" + IntToHex((int)&ptrPC_local,8));
PrintItem("TProg_Control_Thread(" + String(MyPCNo) + "): &i_local 0x" + IntToHex((int)&i_local,8));
PrintItem("TProg_Control_Thread(" + String(MyPCNo) + "): ThreadID " + IntToHex((int)GetCurrentThreadId(), 8));
这将显示在“我的调试”窗口中,用于线程(1)和线程(2):

似乎显示唯一的ThreadID,但每个线程中两个变量的地址相同


我是否正确理解线程特定变量的概念?我应该在每个线程中看到变量的不同地址,这样它们就不会互相碰撞吗?

像往常一样,我在这里得到了很好的建议。Ulrich建议我尝试一个最小的可重复的例子。我花了一段时间,但我发现有人写了一个Delphi测试用例。我用C++重写了它,它确实是我对线程局部变量的期望。

这里是代码(在ActuCabelo C++控制台应用程序中):

#包括
#包括
#布拉格语hdrstop
#包括
#包括
//---------------------------------------------------------------------------
//线程局部变量使用此声明
__declspec(线程)char TestVar[256];
/*控制台窗口上的输出:
main()调用Test()。
调用Test()时的原始TestVar(应为空):
TestVar的地址:005621F0
Test()出口处的新TestVar:Asdf0
正在启动调用Test()的新TTestThread。
正在启动调用Test()的新TTestThread。
调用Test()时的原始TestVar(应为空):
TestVar的地址:0058F128
Test()出口处的新TestVar:Asdf1
调用Test()时的原始TestVar(应为空):
TestVar的地址:0058F500
Test()出口处的新TestVar:Asdf2
main()出口处的TestVar(应为Asdf0)Asdf0
*/
//---------------------------------------------------------------------------
//如果我按如下方式更改声明,程序将无法正常工作
//char-TestVar[256];
/*控制台窗口上的输出:
main()调用Test()。
调用Test()时的原始TestVar(应为空):
TestVar的地址:00421A60
Test()出口处的新TestVar:Asdf0
正在启动调用Test()的新TTestThread。
正在启动调用Test()的新TTestThread。
调用Test()时的原始TestVar(应为空):Asdf0
TestVar的地址:00421A60
Test()出口处的新TestVar:Asdf1
调用Test()时的原始TestVar(应为空):Asdf1
TestVar的地址:00421A60
Test()出口处的新TestVar:Asdf2
main()出口处的TestVar(应为Asdf0)Asdf2
*/
//---------------------------------------------------------------------------
int i;
//---------------------------------------------------------------------------
无效测试(无效){
printf(“调用Test()时的原始TestVar(应为空):%s\n”,TestVar);
printf(“TestVar的地址:%08X\n”,&TestVar);
sprintf(TestVar,“Asdf%d”,i);
i++;
printf(“Test()出口处的新TestVar:%s\n”,TestVar);
}
//---------------------------------------------------------------------------
类TTestThread:公共TThread
{
私人:
受保护的:
void uu fastcall Execute();
公众:
__快速调用TTestThread(bool CreateSuspended);
};
//---------------------------------------------------------------------------
__快速调用TTestThread::TTestThread(bool CreateSuspended)
:TThread(CreateSuspended)
{
FreeOnTerminate=true;
}
//---------------------------------------------------------------------------
void uu fastcall TTesthread::Execute()
{
Test();
}
//---------------------------------------------------------------------------
//基于post-from的测试代码[https://ibeblog.com/2010/08/17/delphi-thread-variables/][1]
这是一个德尔菲代码,我用C++重写了Borland的代码。
//
/*该海报的评论:
Delphi的一个鲜为人知的特性是线程变量。线程变量
是变量,可以为中的每个线程包含不同的值
应用它们被定义为正则变量,唯一的区别是
将“var”关键字替换为“threadvar”。在下面的示例中,我将
向您展示它们如何在小型控制台应用程序中工作。注意,我使用了
TThread类是为了方便起见,但实际上您只需要它
对于过程代码,您可以向TThread子类添加字段以存储
为每个线程输入数据。该示例使用主线程和分离的
线程向您展示它是如何工作的。
01程序测试;
02
03{$APPTYPE控制台}
04
05用途
06系统,类;
07
08型
09 TTesthread=class(TThread)
10受保护
11程序执行;推翻
12公众
13.建造师创建;
14结束;
15
16螺纹变量
17 TestVar:string;
18
19变种
20i:整数;
21
22程序测试;
23开始
24 WriteLn('Original TestVar:'+TestVar);
25 TestVar:=“Asdf”+IntToStr(i);
26公司(i);
27 WriteLn('newtestvar:'+TestVar);
28结束;
29
30{TTesthread}
31
32构造函数TTesthread.Create;
33开始
34(假);
35 FreeOnTerminate:=真;
36端;
37
38程序TTesthread.Execute;
39开始
40试验;
41结束;
42
43开始
44i:=0;
45试验;
46 WriteLn(“起始线程”);
47 TTesthread.Create;
48 ReadLn;
49 WriteLn(TestVar);
50 ReadLn;//防止窗户关闭
51结束。
正如您在运行它时看到的,即使线程变量的内容
如果已更改,则新线程访问该变量时仍然为空。我已经
添加了增量数字,以显示当您按下某个键时
线程已退出,请检查主线程的线程变量内容
线程,它将显示主线程最初存储的Adsf0。
*/
//-----------
PrintItem("TProg_Control_Thread(" + String(MyPCNo) + "): &ptrPC_local 0x" + IntToHex((int)&ptrPC_local,8));
PrintItem("TProg_Control_Thread(" + String(MyPCNo) + "): &i_local 0x" + IntToHex((int)&i_local,8));
PrintItem("TProg_Control_Thread(" + String(MyPCNo) + "): ThreadID " + IntToHex((int)GetCurrentThreadId(), 8));
TProg_Control_Thread(1): &ptrPC_local 0x00AC4788
TProg_Control_Thread(1): &i_local 0x00AC478C
TProg_Control_Thread(1): ThreadID 00001C34

TProg_Control_Thread(2): &ptrPC_local 0x00AC4788
TProg_Control_Thread(2): &i_local 0x00AC478C
TProg_Control_Thread(2): ThreadID 000014C4
#include <vcl.h>
#include <condefs.h>
#pragma hdrstop
#include <stdio.h>
#include <Classes.hpp>
//---------------------------------------------------------------------------
// the thread local variable works with this declaration
__declspec(thread) char TestVar[256];
/* Output on console window:
main() calls Test().
Original TestVar at call to Test() (should be blank):
Address of TestVar : 005621F0
New TestVar at exit of Test(): Asdf0
Starting new TTestThread which calls Test().
Starting new TTestThread which calls Test().
Original TestVar at call to Test() (should be blank):
Address of TestVar : 0058F128
New TestVar at exit of Test(): Asdf1
Original TestVar at call to Test() (should be blank):
Address of TestVar : 0058F500
New TestVar at exit of Test(): Asdf2
TestVar at main() exit (should be Asdf0) Asdf0
*/
//---------------------------------------------------------------------------
// if I change the declaration as follows, program does not work correctly
//char TestVar[256];
/* Output on console window:
main() calls Test().
Original TestVar at call to Test() (should be blank):
Address of TestVar : 00421A60
New TestVar at exit of Test(): Asdf0
Starting new TTestThread which calls Test().
Starting new TTestThread which calls Test().
Original TestVar at call to Test() (should be blank): Asdf0
Address of TestVar : 00421A60
New TestVar at exit of Test(): Asdf1
Original TestVar at call to Test() (should be blank): Asdf1
Address of TestVar : 00421A60
New TestVar at exit of Test(): Asdf2
TestVar at main() exit (should be Asdf0) Asdf2
*/
//---------------------------------------------------------------------------
int i;
//---------------------------------------------------------------------------
void Test(void) {
printf("Original TestVar at call to Test() (should be blank): %s\n", TestVar);
printf("Address of TestVar : %08X\n", &TestVar);
sprintf(TestVar, "Asdf%d", i);
i++;
printf("New TestVar at exit of Test(): %s\n", TestVar);
}
//---------------------------------------------------------------------------
class TTestThread : public TThread
{
private:
protected:
    void __fastcall Execute();
public:
    __fastcall TTestThread(bool CreateSuspended);
};
//---------------------------------------------------------------------------
__fastcall TTestThread ::TTestThread (bool CreateSuspended)
    : TThread(CreateSuspended)
{
FreeOnTerminate = true;
}
//---------------------------------------------------------------------------
void __fastcall TTestThread ::Execute()
{
Test();
}
//---------------------------------------------------------------------------
// test code based on post from [https://ibeblog.com/2010/08/17/delphi-thread-variables/][1]
// this was a piece of Delphi code which I rewrote in C++ for Borland
//
/* comments from that poster:
A somewhat less known feature of Delphi is thread variables. Thread variables
are variables that can contain a different value for each thread in the
application. They are defined like regular variables, the only difference is
that the “var” keyword is replaced with “threadvar”. In the example below I’ll
show you how they work in a small console application. Note that I used the
TThread class for convenience, however in reality you’ll only ever need this
for procedural code as you can add fields to your TThread subclass to store
data in for each thread. The example uses the main thread and a separated
thread to show you how it works.

01  program ThreadVarTest;
02
03  {$APPTYPE CONSOLE}
04
05  uses
06    SysUtils, Classes;
07
08  type
09    TTestThread = class(TThread)
10    protected
11      procedure Execute; override;
12    public
13      constructor Create;
14    end;
15
16  threadvar
17    TestVar: string;
18
19  var
20    i: Integer;
21
22  procedure Test;
23  begin
24    WriteLn('Original TestVar: ' + TestVar);
25    TestVar := 'Asdf' + IntToStr(i);
26    Inc(i);
27    WriteLn('New TestVar: ' + TestVar);
28  end;
29
30  { TTestThread }
31
32  constructor TTestThread.Create;
33  begin
34    inherited Create(False);
35    FreeOnTerminate := True;
36  end;
37
38  procedure TTestThread.Execute;
39  begin
40    Test;
41  end;
42
43  begin
44    i := 0;
45    Test;
46    WriteLn('Starting thread.');
47    TTestThread.Create;
48    ReadLn;
49    WriteLn(TestVar);
50    ReadLn; // Prevent window from closing
51  end.

As you can see when running it, even though the content of the thread variable
was changed, the variable was still empty when accessed by the new thread. I’ve
added the incremental number to show you that when after you press a key when
the thread has exited and you check the thread variable content for the main
thread, it will show Adsf0 as it was stored by the main thread originaly.
*/
//---------------------------------------------------------------------------
#pragma argsused
int main(int argc, char* argv[])
{
i = 0;
printf("main() calls Test().\n");
Test(); // after the first call to Test, TestVar should be "Asdf0"
printf("Starting new TTestThread which calls Test().\n");
// create thread
new TTestThread(false); // create and call Test()

// do it again
printf("Starting new TTestThread which calls Test().\n");
new TTestThread(false); // create and call Test()

printf("TestVar at main() exit (should be Asdf0) %s\n", TestVar);   // after 3 calls to Test, this TestVar should still be "Asdf0"
//
// All values for &TestVar should be different
//
return 0;
}
//---------------------------------------------------------------------------