There is queue with links of files to download. I'm trying find the way to continue downloading when application goes to suspend mode.
According to official microsoft documentation suitable class for this is BackgroundDownloader, but it's handles only one current downloading process. It looks wrong to call in loop CreateDownload() method for every link without waiting for the completion of previous links, isn't right?
More logical in my opinion is using in-process background task. I see it this way:
Implement Run(IBackgroundTaskInstance) method of interface IBackgroundTask (it should stay alive even when app is suspended, right?)
Using custom event transmit the queue to the implemented method
Inside Run(IBackgroundTaskInstance) method use BackgroundDownloader (by implementing the execution of one instance at a time)
But I'm stuck even with simple implementation for one file downloading. Bellow my Run(IBackgroundTaskInstance) method implementation:
void Task::DownloaderTask::Run(IBackgroundTaskInstance ^ taskInstance)
{
TaskDeferral = taskInstance->GetDeferral();
std::wstring filename = L"Pleiades_large.jpg";
Uri^ uri = ref new Uri(ref new Platform::String(L"https://upload.wikimedia.org/wikipedia/commons/4/4e/Pleiades_large.jpg"));
Concurrency::create_task(KnownFolders::GetFolderForUserAsync(nullptr, KnownFolderId::PicturesLibrary))
.then([this, filename, uri](StorageFolder^ picturesLibrary)
{
return picturesLibrary->CreateFileAsync(ref new Platform::String(filename.c_str()), CreationCollisionOption::GenerateUniqueName);
}).then([this, filename, uri](StorageFile^ destinationFile) {
BackgroundDownloader^ downloader = ref new BackgroundDownloader();
DownloadOperation^ download = downloader->CreateDownload(uri, destinationFile);
download->StartAsync();
}).then([this](Concurrency::task<void> previousTask)
{
try
{
previousTask.get();
TaskDeferral->Complete();
}
catch (Platform::Exception^ ex)
{
wchar_t buffer[1024];
swprintf_s(buffer, L"Exception: %s", ex->Message);
OutputDebugString(buffer);
}
});
}
The code above only creates empty file, but using the same code without BackgroundTask it works correctly. I didn't find any restrictions for BackgroundDownloader inside BackgroundTask.
So, my questions are:
Is it right way of usage BackgroundTask?
Is there another approach to solving the problem?
Is this problem solvable at all?
I've found the cause of the unexpected behavior:
The line of code TaskDeferral->Complete(); was at the end of the method at first while it should be at the end of async call.
Therefore, initial implementation (published in question) is correct.
All that had to be done was to Rebuild project.
Related
I'm trying to implement a very simple, local, HTTP server for my C++ application — I'm using XCode on macOS. I have to implement it from within a dynamically loaded library rather than the "main" thread of the program. I decided to try using boost::beast since another part of the application uses boost libraries already. I'm trying to implement this example, but within the context of my library, and not as part its main program.
The host application for this library calls on the following function to start a localhost server, but crashes when instantiating "acceptor":
extern "C" BASICEXTERNALOBJECT_API long startLocalhost(TaggedData* argv, long argc, TaggedData * retval) {
try {
string status;
retval->type = kTypeString;
auto const address = net::ip::make_address("127.0.0.1");
unsigned short port = static_cast<unsigned short>(std::atoi("1337"));
net::io_context ioc{1};
tcp::acceptor acceptor{ioc, {address, port}}; // <-- crashes on this line
tcp::socket socket{ioc};
http_server(acceptor, socket);
ioc.run();
status = "{'status':'ok', 'message':'localhost server started!'}";
retval->data.string = getNewBuffer(status);
}
catch(std::exception const& e)
{
string status;
//err_msg = "Error: " << e.what() << std::endl;
status = "{'status':'fail', 'message':'Error starting web server'}";
retval->data.string = getNewBuffer(status);
}
return kESErrOK;
}
When stepping through the code, I see that XCode reports an error when the line with tcp::acceptor ... is executed:
Thread 1: EXC_BAD_ACCESS (code=1, address=0x783c0a3e3f22650c)
and is highlighted at the single line of code in a function in scheduler.h:
//Get the concurrency hint that was used to initialize the scheduler.
int concurrency_hint() const
{
return concurrency_hint_; //XCode halts here
}
I'm debating as to whether or not I should include a different C++ web server, like Drogon, instead of boost::beast, but I thought I would post here to see if anybody had any insight as to why the crash is happening in this case.
Update
I found a fix that is a workaround for my particular circumstances, hopefully it can help others running into this issue.
The address to the service_registry::create static factory method resolves correctly when I add ASIO_DECL in front of the methods declaration in asio/detail/service_registry.hpp.
It should look like this:
// Factory function for creating a service instance.
template <typename Service, typename Owner>
ASIO_DECL static execution_context::service* create(void* owner);
By adding ASIO_DECL in front of it, it resolves correctly and the scheduler and kqueue_reactor objects initialize properly avoiding the bad access to concurrency_hint().
In my case I am trying to use non-Boost ASIO inside of a VST3 audio plug-in running in Ableton Live 11 on macOS on an M1 processor. Using the VST3 plug-in in I'm getting this same crash. Using the same plug-in in other DAW applications, such as Reaper, does not cause the crash. It also does not occur for Ableton Live 11 on Windows.
I've got it narrowed down to the following issue:
In asio/detail/impl/service_registry.hpp the following method attempts to return a function pointer address to a create/factory method.
template <typename Service>
Service& service_registry::use_service(io_context& owner)
{
execution_context::service::key key;
init_key<Service>(key, 0);
factory_type factory = &service_registry::create<Service, io_context>;
return *static_cast<Service*>(do_use_service(key, factory, &owner));
}
Specifically, this line: factory_type factory = &service_registry::create<Service, io_context>;
When debugging in Xcode, in the hosts that work, when inspecting
factory, it shows the correct address linking to the service_registry::create<Service, io_context> static method.
However, in Ableton Live 11, it doesn't point to anything - somehow the address to the static method does not resolve correctly. This causes a cascade of issues, ultimately leading up to trying to invoke the factory function pointer in asio/asio/detail/impl/service_registry.ipp in the method service_registry::do_use_service. Since it doesn't point to a proper create method, nothing is created, it results in uninitialized objects, including the scheduler instance.
Therefore, when calling scheduler_.concurrency_hint() in kqueue_reactor.ipp the scheduler is uninitialized, and the EXC_BAD_ACCESS error results.
It's unclear to me why under some host processes, dynamically loading the plug-in cannot resolve the static method address, but others have no problem. In my case I compiled asio.hpp for standalone ASIO into the plug-in directly, there was no linking.
The best guesses I can come up with are
maybe your http_server might start additional threads or even fork. This might cause io_context and friends to be accessed after startLocalhost returned. To explain the crash location appearing to be at the indicated line, I could add the heuristic that something is already off during the destructor for ioc
the only other idea I have is that actually the opening/binding of the acceptor throws, but due to possible incompatibilities of types in the shared module vs the main program, the exception thrown is not actually caught and causes abnormal termination. This might happen more easily if the main program also uses Boost libraries, but a different copy (build/version) of them.
In this case there's a simple thing you can do: split up initialization and use the overloads that take error_code to instead use them.
In windows runtime component project (BackgroundTask c++)
#include "pch.h"
#include "BackgroundTask.h"
using namespace Platform;
namespace SyncBackground {
void BackgroundTask::Run(IBackgroundTaskInstance^ taskInstance) {
_taskInstance = taskInstance;
taskInstance->Canceled += ref new BackgroundTaskCanceledEventHandler(this, &BackgroundTask::OnCanceled);
_deferral = taskInstance->GetDeferral();
OutputDebugString(L"Debug: CPP\r\n");
}
void BackgroundTask::OnCanceled(IBackgroundTaskInstance^ sender, BackgroundTaskCancellationReason reason) {
_deferral->Complete();
}
}
I try ApplicationTrigger from c# project, but OutputDebugString write only one times from first trigger. In the same BackgroundTask C#, Debug.WriteLine() write every trigger.
Then why in c++ do it only one times? And how make it work look like c# (i need send some data and command via trigger)
Thank
I need it still run background
If I understand correctly, you just want to run background tasks indefinitely. If so, even if you don't call TaskDeferral.Complete();, it won't still run background, after a period of time, it will still be terminated. In that case, you can refer to this document to configure. But it mentions if you use it, you can't put an app into the Microsoft Store. If not, please point me out.
I am doing low level audio processing on iOS. As a result parts of my application are written in c++.
There I create and write to audio files. Files are created using ExtAudioFileCreateWithURL and written to using ExtAudioFileWriteAsync. Files are closed using ExtAudioFileDispose.
Sometimes files need to be deleted.
How do I delete files created with ExtAudioFileCreateWithURL in c++?
Since the files are opened with a CFURLRef the function CFURLDestroyResource seems to be the way to do this, but this function is deprecated and it is unclear to me what would replace this function.
I eventually managed to tackle this problem by writing a helper function in a Objective-C file and calling that function from the C++ code.
bool removeItemAtURL(CFURLRef url) {
NSFileManager *fileManager = [NSFileManager defaultManager];
return [fileManager removeItemAtURL: (__bridge NSURL *)url error: NULL];
}
Although this works I am unsure if it is save to use the NSFilemanger object in a time critical audio rendering thread. If so then it would be best to let deletion of files be handled in a different thread.
I've written my own access layer to a game engine. There is a GameLoop which gets called every frame which lets me process my own code. I'm able to do specific things and to check if these things happened. In a very basic way it could look like this:
void cycle()
{
//set a specific value
Engine::setText("Hello World");
//read the value
std::string text = Engine::getText();
}
I want to test if my Engine-layer is working by writing automated tests. I have some experience in using the Boost Unittest Framework for simple comparison tests like this.
The problem is, that some things I want the engine to do are just processed after the call to cycle(). So calling Engine::getText() directly after Engine::setText(...) would return an empty string. If I would wait until the next call of cycle() the right value would be returned.
I now am wondering how I should write my tests if it is not possible to process them in the same cycle. Are there any best practices? Is it possible to use the "traditional testing" approach given by Boost Unittest Framework in such an environment? Are there perhaps other frameworks aimed at such a specialised case?
I'm using C++ for everything here, but I could imagine that there are answers unrelated to the programming language.
UPDATE:
It is not possible to access the Engine outside of cycle()
In your example above, std::string text = Engine::getText(); is the code you want to remember from one cycle but execute in the next. You can save it for later execution. For example - using C++11 you could use a lambda to wrap the test into a simple function specified inline.
There are two options with you:
If the library that you have can be used synchronously or using c++11 futures like facility (which can indicate the readyness of the result) then in your test case you can do something as below
void testcycle()
{
//set a specific value
Engine::setText("Hello World");
while (!Engine::isResultReady());
//read the value
assert(Engine::getText() == "WHATEVERVALUEYOUEXPECT");
}
If you dont have the above the best you can do have a timeout (this is not a good option though because you may have spurious failures):
void testcycle()
{
//set a specific value
Engine::setText("Hello World");
while (Engine::getText() != "WHATEVERVALUEYOUEXPECT") {
wait(1 millisec);
if (total_wait_time > 1 sec) // you can put whatever max time
assert(0);
}
}
What is the best way to go about monitoring a folder to see when an image file has been added to it? Files are added approximately once a minute and the naming goes like this... image0001.jpg, image0002.jpg, image0003.jpg etc. I need to know when a file has been written to the folder so that my app can access and use it.
Look into directory change notifications.
As per previously mentioned, the directory change notifications is what you want.
I have looked into them as well, and the caveat I have seen is that windows will fire off the notification when the file starts to be written to the folder. If the file is large enough then you will receive the notification before the file has finished being written.
Check out this google search for various solutions for waiting until the file is completely written
Edit: I just saw that the question was tagged with c++, and I linked to a .Net search. Although what I provided may not be the correct language, I would think that you will still have the same issues on Windows no matter what system you are coding with.
FileSystemWatcher should be able to do that for you.
Change notifactions may cause some overhead, if you've NTFS, consider NTFS change journals.
You can use a polling method to monitor the folder. The loop will execute every 5 seconds, for example.
This method returns a list of new files:
List<string> files = new List<string>();
string path = #"C:\test\"; // whatever the path is
public List<string> GetNewFiles(string path)
{
// store all the filenames (only .jpg files) in a list
List<string> currentFiles = System.IO.Directory.GetFiles(path, "*.jpg");
if ( currentFiles.Count() > files.Count() )
{
count = newFiles.Length - files.Length;
List<string> newFiles = new List<string>();
foreach ( string file in currentFiles )
{
if ( !files.Contains(file) )
{
newFiles.Add(file);
}
}
}
files = currentFiles;
return newFiles;
}
This is the method that will poll every 5 seconds and call the previous method.
public void MonitorFolder()
{
while (true)
{
List<string> newFiles = GetNewFiles(path);
System.Threading.Thread.Sleep(5000); // 5000 milliseconds
}
}
Synch.variant FindFirstChangeNotification
Asynch.variant ReadDirectoryChangesW
This was the top google result for my search so I'll add this as an answer.
If you're using Qt, there's QFileSystemWatcher. I didn't know this existed and we happened to be using Qt, so I wasted more than a few hours using FindFirstChangeNotification to rewrite what was readily available to me until a colleague showed me the light.
Good learning experience though.
inotify might be your thing