2

我们的产品包含一个任务管理器系统,允许应用程序在预定的时间间隔内运行 DLL 中的代码,指定有关任务失败是否应禁用相关应用程序的规则等。主要用于数据上传、数据下载,本地数据库维护等。使用的功能之一是通过NTP同步设备时间并设置操作系统的时区信息。为此,我们使用 OpenNetCF 的 DateTimeHelper 类,它似乎充当了 Win32 P/Invokes 的包装器。

任务管理器的其他功能之一是,如果任务运行时间超过其分配的时间窗口,任务管理器将 Thread.Abort() 它以允许其他任务运行。我们看到了惊人数量的线程中止,其中堆栈中最高的函数是 OpenNetCF.WindowsCE.NativeMethods.SetTimeZoneInformation()。为什么底层 P/Invoke (SetTimeZoneInfo) 会挂这么长时间?

我们的代码在 Windows CE 4.2 上运行,用户群更小,在 Windows CE 5.0 上运行——这里的代码在两个版本之间是相同的。到目前为止,我已经看到这种情况发生在 4.2 设备上,但从未在 5.0 上发生过,即使 5.0 上的用户数量较少,我想如果它出现在那里我也会看到它。

下面的函数是产生问题的函数。它将时区缩写转换为其全名,然后使用该名称查找正确的时区并尝试将设备的当前时区设置为该时区。

        public static bool SetTimeZone(string timeZoneAbbreviation)
        {
            字符串 TimeZoneInfo = string.Empty;
            bool timeZoneChanged = false;

            开关(时区缩写)
            {
                阿拉斯加案例:
                    TimeZoneInfo = ALASKA_TZN;
                    休息;
                案例 ALASKA_ALT:
                    TimeZoneInfo = ALASKA_TZN;
                    休息;
                大西洋案例:
                    时区信息=大西洋_TZN;
                    休息;
                案例大西洋_ALT:
                    时区信息=大西洋_TZN;
                    休息;
                案例中心:
                    时区信息 = CENTRAL_TZN;
                    休息;
                案例 CENTRAL_ALT:
                    时区信息 = CENTRAL_TZN;
                    休息;
                东部案例:
                    TimeZoneInfo = EASTERN_TZN;
                    休息;
                印第安纳州案例:
                    时区信息 = 印第安纳州 TZN;
                    休息;
                夏威夷案例:
                    时区信息 = HAWAII_TZN;
                    休息;
                案例山:
                    时区信息 = MOUNTAIN_TZN;
                    休息;
                亚利桑那案例:
                    时区信息 = ARIZONA_TZN;
                    休息;
                太平洋案例:
                    时区信息 = PACIFIC_TZN;
                    休息;
                案例 PACIFIC_ALT:
                    时区信息 = PACIFIC_TZN;
                    休息;

                默认:                    
                    休息;
            }

            时区信息 += "\0";

            TimeZoneCollection tzc = new TimeZoneCollection();
            tzc.Initialize();

            foreach(时区信息 tzc 中的 tzi)
            {
                字符串 tzDisplayName = tzi.DisplayName.TrimEnd(new char[]{'\\','0'});

                if (tzDisplayName.ToUpper(CultureInfo.CurrentCulture).Equals(TimeZoneInfo.ToUpper(CultureInfo.CurrentCulture)))
                {
                    DateTimeHelper.SetTimeZoneInformation(tzi);
                    System.Globalization.CultureInfo.CurrentCulture.ClearCachedData();
                    timeZoneChanged = true;
                    休息;
                }
            }

            返回时区改变;
        }

一如既往地感谢您的帮助。有什么想法吗?

4

1 回答 1

1

DateTimeHelper.SetTimeZoneInformation 调用是对SetTimezoneInformation API的 P/Invoke 的一个非常薄的包装器(我刚刚在源代码中验证了这一点)。它基本上进行调用并检查返回码——仅此而已,因此几乎可以排除 SDF 本身是根本原因。

接下来,查看SetTimezoneInformation 的 MSDN 文档,这是一个非常简单的同步调用,它返回 TRUE 或 FALSE。这告诉我 API 也可能不是根本原因。

在 CE 中要记住的一件事是,您永远不能假设该平台是完美的,因为它是由 OEM 完成的,因此可能会有变化。您在 4.2 而不是 5.0 中看到失败的事实将导致我检查以下内容:

  1. 确保 4.2 设备映像已应用所有 QFE
  2. 查看 4.2 和 5.0 之间是否存在时区内容的操作系统代码差异(我对此表示怀疑,但我不再安装 PB 4.2)。
  3. 检查 OEM 实施以设置时间。更改区域会隐式调用来设置时间,并且 4.2 BSP 中可能存在一个错误,该错误可能会导致您遇到锁定或竞争。
于 2009-01-05T18:04:16.990 回答