2023-04-28 23:22:17 +04:00
|
|
|
// Thanks to RetroArch/Libretro team for this idea
|
|
|
|
|
// This is improved version of the original idea
|
|
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
|
|
|
|
|
#include "pch.h"
|
|
|
|
|
#include <ppl.h>
|
|
|
|
|
#include <ppltasks.h>
|
|
|
|
|
#include <wrl.h>
|
|
|
|
|
#include <wrl/implements.h>
|
|
|
|
|
|
2023-04-30 08:54:54 +04:00
|
|
|
#include "Common/Log.h"
|
|
|
|
|
#include "UWPUtil.h"
|
2023-04-28 23:22:17 +04:00
|
|
|
|
|
|
|
|
using namespace Windows::UI::Core;
|
|
|
|
|
|
|
|
|
|
// Don't add 'using' 'Windows::Foundation'
|
|
|
|
|
// it might cause confilct with some types like 'Point'
|
|
|
|
|
|
|
|
|
|
#pragma region Async Handlers
|
|
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
|
T TaskHandler(std::function<concurrency::task<T>()> wtask, T def)
|
|
|
|
|
{
|
|
|
|
|
T result = def;
|
|
|
|
|
bool done = false;
|
|
|
|
|
wtask().then([&](concurrency::task<T> t) {
|
|
|
|
|
try
|
|
|
|
|
{
|
2023-04-30 08:54:54 +04:00
|
|
|
result = t.get();
|
2023-04-28 23:22:17 +04:00
|
|
|
}
|
|
|
|
|
catch (Platform::Exception^ exception_)
|
|
|
|
|
{
|
2023-04-30 08:54:54 +04:00
|
|
|
ERROR_LOG(FILESYS, FromPlatformString(exception_->Message).c_str());
|
2023-04-28 23:22:17 +04:00
|
|
|
}
|
|
|
|
|
done = true;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
CoreWindow^ corewindow = CoreWindow::GetForCurrentThread();
|
|
|
|
|
while (!done)
|
|
|
|
|
{
|
|
|
|
|
try {
|
|
|
|
|
if (corewindow) {
|
|
|
|
|
corewindow->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
corewindow = CoreWindow::GetForCurrentThread();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch (...) {
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
|
T TaskPass(Windows::Foundation::IAsyncOperation<T>^ task, T def)
|
|
|
|
|
{
|
|
|
|
|
return TaskHandler<T>([&]() {
|
|
|
|
|
return concurrency::create_task(task).then([](T res) {
|
|
|
|
|
return res;
|
|
|
|
|
});
|
|
|
|
|
}, def);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool ActionPass(Windows::Foundation::IAsyncAction^ action);
|
|
|
|
|
|
|
|
|
|
#pragma endregion
|
|
|
|
|
|
|
|
|
|
// Now it's more simple to execute async task
|
|
|
|
|
// @out: output variable
|
|
|
|
|
// @task: async task
|
|
|
|
|
template<typename T>
|
|
|
|
|
void ExecuteTask(T& out, Windows::Foundation::IAsyncOperation<T>^ task)
|
|
|
|
|
{
|
2023-04-30 08:54:54 +04:00
|
|
|
try {
|
|
|
|
|
out = TaskPass<T>(task, T());
|
|
|
|
|
}
|
|
|
|
|
catch (...) {
|
|
|
|
|
out = T();
|
|
|
|
|
}
|
2023-04-28 23:22:17 +04:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// For specific return default value
|
|
|
|
|
// @out: output variable
|
|
|
|
|
// @task: async task
|
|
|
|
|
// @def: default value when fail
|
|
|
|
|
template<typename T>
|
|
|
|
|
void ExecuteTask(T& out, Windows::Foundation::IAsyncOperation<T>^ task, T def)
|
|
|
|
|
{
|
2023-04-30 08:54:54 +04:00
|
|
|
try{
|
|
|
|
|
out = TaskPass<T>(task, def);
|
|
|
|
|
}
|
|
|
|
|
catch (...) {
|
|
|
|
|
out = def;
|
|
|
|
|
}
|
2023-04-28 23:22:17 +04:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Async action such as 'Delete' file
|
|
|
|
|
// @action: async action
|
|
|
|
|
// return false when action failed
|
|
|
|
|
bool ExecuteTask(Windows::Foundation::IAsyncAction^ action);
|