I'm building an small App that gather data from website. and I managed to gather data.
Following picture depicts what my app does.
when I click the button "시작", my App get html of the specific page, and get data from it. This works are done in ViewModel class, and I bind the result data to ViewPage, observing mvvm pattern I think.
Following source code shows logic that I wrote for my program.
public class MainPageViewModel : Observable
{
public SiseDataList dataList { get; set; } = new SiseDataList();
public MainPageViewModel()
{
ButtonClick = new RelayCommand(Click);
}
public async void Click()
{
// ... omitted ..
foreach (var i in tmp_list)
{
if (dataList.Count == 0)
{
dataList.Add(i);
}
else if (dataList.Last().date < i.date)
{
dataList.Add(i);
}
}
OnPropertyChanged("data");
}
public RelayCommand ButtonClick { get; set; }
}
I bind data_list
data to viewPage
, GridView
.
Now, I think I can say what I want to implement.
If I click "시작" button of my App, I want to execute Click function every 20 seconds.
Luckily, I could easily find the document about periodic work in UWP. Link: create-a-periodic-work-item
So, I tried to implement that functionality, but I failed.
First I tried the following:
public MainPageViewModel()
{
ButtonClick = new RelayCommand(Regist);
}
public async void Regist()
{
TimeSpan period = TimeSpan.FromSeconds(60);
ThreadPoolTimer PeriodicTimer = ThreadPoolTimer.CreatePeriodicTimer(async (source) =>
{
Dispatcher.RunAsync(CoreDispatcherPriority.High,
() =>
{
// UI components can be accessed within this scope.
Click();
});
}, period);
}
public async void Click() //...omitted..
I put Click()
function in Dispatcher
, because I think Click()
function call OnPropertyChanged()
from INotifyPropertyChanged
interface.
but the Intellisense tells me, It can't find any Dispatcher
name in context.
So I just right clicked on it and clicked refactoring menu, and then, That sentence becomes System.ServiceModel.Dispatcher.RunAsync...
but It does not work. I found CoreDispatcher
class in documents so I used it. I wrote CoreDispatcher.RunAsync(....)
, But It is not a static class I can't use that syntax.
I googled and I tried Window.Current.Dispatcher.RunAsync(....)
but it return exception "Windows.UI.Xaml.Windows.Current.get
returns null
".
finally, I tried following code.
TimeSpan period = TimeSpan.FromSeconds(60);
ThreadPoolTimer PeriodicTimer = ThreadPoolTimer.CreatePeriodicTimer((source) =>
{
Click();
}, period);
But program crashed while executing Click
function add element at dataList List, I think other thread(kind of UI thread...?) is watching or holding that list as I bind it to view Page. And It returns exception "Exception from HRESULT: 0x8001010E (RPC_E_WRONG_THREAD)."
How can I periodically execute a specific function in UWP?
You need to use Dispatcher
of the application (which matches the main window's dispatcher):
Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(
CoreDispatcherPriority.High,
() =>
{
// UI components can be accessed within this scope.
Click();
});
The reason your approach did not work is that it is not possible to call Window.Current.Dispatcher
from non-UI thread, as Window.Current
is only accessible on UI thread. However Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher
can be accessed from anywhere.
User contributions licensed under CC BY-SA 3.0