在Windows CE .NET 4.2中,为什么SetTimeZoneInfo会挂起?

时间:2009-01-05 17:32:43

标签: timezone pinvoke windows-ce opennetcf

我们的产品包含一个任务管理器系统,允许应用程序在计划的时间间隔内运行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)
        {
            string TimeZoneInfo = string.Empty;
            bool timeZoneChanged = false;

            switch (timeZoneAbbreviation)
            {
                case ALASKA:
                    TimeZoneInfo = ALASKA_TZN;
                    break;
                case ALASKA_ALT:
                    TimeZoneInfo = ALASKA_TZN;
                    break;
                case ATLANTIC:
                    TimeZoneInfo = ATLANTIC_TZN;
                    break;
                case ATLANTIC_ALT:
                    TimeZoneInfo = ATLANTIC_TZN;
                    break;
                case CENTRAL:
                    TimeZoneInfo = CENTRAL_TZN;
                    break;
                case CENTRAL_ALT:
                    TimeZoneInfo = CENTRAL_TZN;
                    break;
                case EASTERN:
                    TimeZoneInfo = EASTERN_TZN;
                    break;
                case INDIANA:
                    TimeZoneInfo = INDIANA_TZN;
                    break;
                case HAWAII:
                    TimeZoneInfo = HAWAII_TZN;
                    break;
                case MOUNTAIN:
                    TimeZoneInfo = MOUNTAIN_TZN;
                    break;
                case ARIZONA:
                    TimeZoneInfo = ARIZONA_TZN;
                    break;
                case PACIFIC:
                    TimeZoneInfo = PACIFIC_TZN;
                    break;
                case PACIFIC_ALT:
                    TimeZoneInfo = PACIFIC_TZN;
                    break;

                default:                    
                    break;
            }

            TimeZoneInfo += "\0";

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

            foreach (TimeZoneInformation tzi in tzc)
            {
                string 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;
                    break;
                }
            }

            return timeZoneChanged;
        }

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

1 个答案:

答案 0 :(得分:1)

DateTimeHelper.SetTimeZoneInformation调用是围绕P {Invoke到SetTimezoneInformation API的一个非常薄的包装器(我刚刚在源代码中验证了它)。它基本上会调用并检查返回代码 - 仅此而已,因此几乎排除了SDF本身作为根本原因。

接下来,查看MSDN doc for SetTimezoneInformation,这是一个非常简单的同步调用,返回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中存在潜在锁定或竞争的错误。