【问题标题】:Does WinRT _really_ support thread local storage functions (Tls*)?WinRT _really_ 是否支持线程本地存储函数 (Tls*)?
【发布时间】:2015-01-15 17:01:13
【问题描述】:

我正在将旧版 Windows 代码移植到 Windows 运行时 (WinRT),特别是 Windows Phone 8.1。该代码包含对线程本地存储函数(如 TlsAlloc、TlsFree、TlsGetValue 和 TlsSetValue)的调用。根据MSDN的"Win32 and COM for Windows Runtime apps (system)"页面,WinRT下支持这四个TLS功能。以TlsAlloc documentation为例,读一读:

Windows Phone 8.1:Windows Phone Store 支持此功能 Windows Phone 8.1 及更高版本上的应用程序。当一个 Windows Phone Store 应用程序 调用此函数时,它会替换为对 FlsAlloc 的内联调用。 有关函数文档,请参阅 FlsAlloc。

当我在我的旧代码中#include 指示的头文件 Processthreadsapi.h 时,编译失败:

错误 C2039:“TlsAlloc”:不是“全局命名空间”的成员

检查 Processthreadsapi.h 说明为什么它对我没有帮助:

/***********************************************************************************
*                                                                                  *
* processthreadsapi.h -- ApiSet Contract for api-ms-win-core-processthreads-l1     *
*                                                                                  *
* Copyright (c) Microsoft Corporation. All rights reserved.                        *
*                                                                                  *
***********************************************************************************/
. . .
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
. . .
#ifndef FLS_OUT_OF_INDEXES
#define FLS_OUT_OF_INDEXES ((DWORD)0xFFFFFFFF)
#endif

#define TLS_OUT_OF_INDEXES ((DWORD)0xFFFFFFFF)

_Must_inspect_result_
WINBASEAPI
DWORD
WINAPI
TlsAlloc(
    VOID
    );


WINBASEAPI
LPVOID
WINAPI
TlsGetValue(
    _In_ DWORD dwTlsIndex
    );


WINBASEAPI
BOOL
WINAPI
TlsSetValue(
    _In_ DWORD dwTlsIndex,
    _In_opt_ LPVOID lpTlsValue
    );


WINBASEAPI
BOOL
WINAPI
TlsFree(
    _In_ DWORD dwTlsIndex
    );
. . .
#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) */
. . .

问题很明确:WinRT 属于 WINAPI_PARTITION_APP 的世界,而不是 WINAPI_PARTITION_DESKTOP。因此,当我为 WinRT 编译我的应用程序时,我没有得到任何这些符号和函数声明。

这只是一个 Windows 标头问题,MS 应该在其中包含 WinRT 的 Tls* 函数吗?还是与文档相反,WinRT 不支持线程本地存储?

【问题讨论】:

  • 您只是查看了文件的错误部分。 TlsAlloc() 的 WinRT 版本出现在第 #403 行。一个内联函数,它调用 FlsAlloc()。当我尝试它时,调用它也不是问题。只需#include <Windows.h> 即可。
  • @HansPassant 我们必须查看不同的头文件。在我的 c:\Program Files (x86)\Windows Phone Kits\8.1\Include\minwin\processthreadsapi.h 副本中,“TlsAlloc”只有一次出现,这来自我上面引用的部分。文件中根本没有出现“FlsAlloc”。第 403 行指向 CreateProcessW 函数声明。即使#include-ing windows.h,VS 的 Intellisense 也无法识别 TlsAlloc。我做错了什么

标签: windows-runtime


【解决方案1】:

是的,确实如此。从 c:\Program Files (x86)\Windows Phone Kits\8.1\Include\minwin\processthreadsapi.h 复制/粘贴,第 #411 行:

// TlsAlloc, TlsFree, TlsGetValue and TlsSetValue are defined as inlines 
// only for the store apps, not for desktop apps
#pragma region Application Family
#if WINAPI_PARTITION_APP && !WINAPI_PARTITION_DESKTOP

#include <fibersapi.h>

FORCEINLINE
_Must_inspect_result_
WINBASEAPI
DWORD
WINAPI
TlsAlloc(
    VOID
    )
{
    return FlsAlloc(NULL);
}
// etc..

您描述的文件是该文件的8.0 版本。当然不知道这是怎么发生的。也许你有一个早期的测试版,也许你复制文件来解决问题。登陆页面is here,我确实下载了 8.1 Update 1 模拟器,但不知道是否也更新了 SDK 头文件。

【讨论】:

  • 很高兴知道我没疯 :-)。事实证明我有 Windows 8.1 SDK Update 3,所以 Peter Torr 建议升级到 Update 4 应该可以解决问题。非常感谢您的有用回复。
【解决方案2】:

这仅在 VS 2013 Update 4 中添加。如果您有较早的安装(包括 Update 4 RC),则不会有更新的标头。

【讨论】:

  • 非常感谢更新到更新 4 的重要提示。这里有一个重要的教训:如果文档声明支持某个功能,请确保您拥有最新的更新。再次感谢!
【解决方案3】:

另一种方法是 __declspec(thread),它可能更易于使用。它可能映射到相同的功能。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-11-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多