private async Task StartListenPropertiesChange(DeviceClient deviceClient)
        {
            var retryCountRemain = _retryCount;

            while (true)
            {
                try
                {
                    var beforeStartGetTwinTimeStamp = DateTime.Now;
                    var twin = await deviceClient.GetTwinAsync();

                    var afterGetTwinTimeStamp = DateTime.Now;
                    ((BaseDiagnosticProvider)_diagnosticProvider).SetSamplingConfigFromTwin(twin.Properties.Desired);
                    Console.WriteLine($"Automatically obtain twin settings from server when start. GetTwinTimeConsume: {(afterGetTwinTimeStamp-beforeStartGetTwinTimeStamp).TotalMilliseconds}");
                    await deviceClient.SetDesiredPropertyUpdateCallback(((BaseDiagnosticProvider)_diagnosticProvider).OnDesiredPropertyChange, null);

                    break;
                }
                catch (Exception e)
                {
                    retryCountRemain--;
                    var randomDelayTime = new Random().Next(_retryAfterMilisecondLowerBound, _retryAfterMilisecondUpperBound);
                    await Task.Delay(randomDelayTime);

                    if (retryCountRemain < 0)
                    {
                        Console.WriteLine("Error occur when get twin settings from server:\n" + e.Message + "\nStop retry and ignore diagnostic.");
                        break;
                    }
                    Console.WriteLine("Error occur when get twin settings from server:\n" + e.Message + "\nRetry...");
                }
            }
        }
        public Task SetDesiredPropertyUpdateCallback(DesiredPropertyUpdateCallback callback, object userContext)
        {
            _userDesiredPropertyUpdateCallback = callback;

            DesiredPropertyUpdateCallback callbackWrapper = (desiredProperties, context) =>
            {
                return(Task.Run(() =>
                {
                    if (_diagnosticProvider.GetSamplingRateSource() == SamplingRateSource.Server)
                    {
                        ((BaseDiagnosticProvider)_diagnosticProvider).OnDesiredPropertyChange(desiredProperties, context);
                    }

                    _userDesiredPropertyUpdateCallback(desiredProperties, context);
                }));
            };

            this.callbackWrapper = callbackWrapper;
            return(_deviceClient.SetDesiredPropertyUpdateCallback(callbackWrapper, userContext));
        }