In the last few weeks, we introduced posting an event from native to managed code with Interop. To continue on Interop topics, we’ll show how to use a task callback in native code.
Three main steps are, create a task, set up time for the task to be triggered, and free the task if no longer needed.
Just a notice here is, when we create a task, there is a parameter “fireInIsr”, setting it “true” means the task will be triggered by interrupt which would be more accurate, but the task needs be done quickly, so if a task is heavy then set to “false” is recommended.
The example in the attachment will show more about this topic. It creates a task, and the task just simply increases a counter by 1 after every one second, also post new counter value to managed side. After 10 seconds (counter is 10) then stop and free the task.
#include "TinyCLR.h"
#define INTERVAL_IN_TICK (1 * 1000 * 10000) // 1 second
uint64_t counter = 0;
const TinyCLR_Interop_Manager* interopManager;
const TinyCLR_Api_Manager* apiManager;
const TinyCLR_Task_Manager* taskManager;
const TinyCLR_NativeTime_Controller* timeManager;
TinyCLR_Task_Reference IncreaseCounterTaskReference;
void IncreaseCounterTaskCallback(const TinyCLR_Task_Manager* self, const TinyCLR_Api_Manager* apiManager, TinyCLR_Task_Reference task, void* arg);
TinyCLR_Result Interop_InteroptTest_InteroptTest_MyNativeClass::DoSomething___VOID(const TinyCLR_Interop_MethodData md) {
auto useInterruptMode = false; // No need to be accurated
void* arguments = nullptr; // arguments
// Init variables
apiManager = reinterpret_cast<const TinyCLR_Api_Manager*>(md.ApiManager->FindDefault(md.ApiManager, TinyCLR_Api_Type::ApiManager));
interopManager = reinterpret_cast<const TinyCLR_Interop_Manager*>(apiManager->FindDefault(apiManager, TinyCLR_Api_Type::InteropManager));
taskManager = reinterpret_cast<const TinyCLR_Task_Manager*>(apiManager->FindDefault(apiManager, TinyCLR_Api_Type::TaskManager));
timeManager = reinterpret_cast<const TinyCLR_NativeTime_Controller*>(apiManager->FindDefault(apiManager, TinyCLR_Api_Type::NativeTimeController));
// Creat task
taskManager->Create(taskManager, IncreaseCounterTaskCallback, arguments, useInterruptMode, IncreaseCounterTaskReference);
// Schedule task
taskManager->Enqueue(taskManager, IncreaseCounterTaskReference, timeManager->ConvertSystemTimeToNativeTime(nullptr, INTERVAL_IN_TICK));
counter = 0;
return TinyCLR_Result::Success;
}
// Implement callback function
void IncreaseCounterTaskCallback(const TinyCLR_Task_Manager* self, const TinyCLR_Api_Manager* apiManager, TinyCLR_Task_Reference task, void* arg)
{
if (task == IncreaseCounterTaskReference)
{
auto data0 = "From Task Callback";
auto data1 = counter++; // Increase counter
auto data2 = 0;
auto data3 = 0;
auto data4 = 0;
auto data5 = 0;
// Post counter to managed
interopManager->RaiseEvent(interopManager, "InteroptTestEvent", data0, (uint64_t)data1, (uint64_t)(data2), data3, data4, data5);
if (counter < 10)
{
// Re-schedule for next time.
taskManager->Enqueue(taskManager, IncreaseCounterTaskReference, timeManager->ConvertSystemTimeToNativeTime(nullptr, INTERVAL_IN_TICK));
}
else
{
// Free a task
taskManager->Free(taskManager, IncreaseCounterTaskReference);
}
}
}