Метка обновления многопоточных часов реального времени

Итак, я создаю приложение UWP на Windows 10 IoT Core и Raspberry Pi 3. Теперь я хочу иметь часы реального времени (без перегрузки всего), чтобы получить точное время (полученное от GPS, но только от системы).

Что я сделал сейчас, так это создал Task с бесконечным циклом while, чтобы получить время и поместить его на метку... Но я не могу понять, почему метка не обновляется в этом цикле while, но все же он обновляется при загрузке страницы. Код, который я использую, можно найти ниже:

public sealed partial class Tripmaster : Page
{
    public Tripmaster()
    {
        this.InitializeComponent();

        lbl_clock.Text = DateTime.Now.ToString("HH:mm:ss");

        start_clock();

        btn_back.Click += Btn_back_Click;
    }

    private void start_clock()
    {
        // Init the clock and start the thread for the clock.
        Task.Run(() => {
            while (true)
            {
                lbl_clock.Text = DateTime.Now.ToString("HH:mm:ss");
                Debug.WriteLine(DateTime.Now.ToString("HH:mm:ss"));
                Task.Delay(500);
            }
        });
    }

    private void Btn_back_Click(object sender, RoutedEventArgs e)
    {
        this.Frame.Navigate(typeof(MainPage));
    }
}

Таким образом, lbl_clock.Text = DateTime.Now.ToString("HH:mm:ss"); работает, но больше никогда не обновляется и падает в цикле while. Есть идеи, как я могу сделать так, чтобы метки обновлялись автоматически и (почти) в реальном времени?

Если я просто закомментирую lbl_clock.Text = DateTime.Now.ToString("HH:mm:ss"); и отлажу его (путем написания строки отладки), это сработает, что я могу сделать? Это действительно важно для этого проекта.


person Robin    schedule 16.06.2018    source источник


Ответы (3)


Поискав намного больше и глубже в коде, я нашел решение.

Итак, теперь я делаю это в приватной пустоте:

private void start_clock()
        {
            // Init the clock and start the thread for the clock.
            Task.Run(async () => {
                while (true)
                {
                    await Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
                    {
                        this.lbl_clock.Text = DateTime.Now.ToString("HH:mm:ss");
                    });
                    await Task.Delay(500);
                }
            });
        }

Это работает как шарм.

person Robin    schedule 16.06.2018

Ваша проблема заключается в попытке доступа к объекту в другой области памяти в текущей задаче. Решение использует «делегаты» (извините за формат ответа, я пишу на мобильном...):

    Private delegate void changuestring (string text);
Private void changuetext (string text)
{
If (lbl_clock.invokerequired)
lbl_clock.invoke(new changuestring(changuetext), text);
Else
lbl_clock.text = text;
}



 private void start_clock()
 { 
// Init the clock and start the thread for the clock. 

Task.Run(() =>
 { 
while (true) 
{ 
changuetext( DateTime.Now.ToString("HH:mm:ss")); Debug.WriteLine(DateTime.Now.ToString("HH:mm:ss")); 
Task.Delay(500); 
} 
}); 
}
person D3ivid    schedule 16.06.2018

Существует еще одно решение. Для выполнения кода и обновления свойства элемента в потоке пользовательского интерфейса вы также можете использовать инфраструктуру MVVM Light для решения этой проблемы. MVVM (Model-View-ViewModel) — это архитектурный шаблон программного обеспечения, который обеспечивает четкое разделение проблем между элементами управления пользовательского интерфейса и их логикой. Вы можете обратиться к этой теме.

person Michael Xu - MSFT    schedule 18.06.2018