Interop: Creating a Task

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));
			// Free a task
			taskManager->Free(taskManager, IncreaseCounterTaskReference);