Search code examples
timerc++-cli

Timer in C++/CLI


I am trying to find timer in my application in C++/CLI(I using windows forms). Timer will be update information in labels constantly. I need to use timer without freezing form. I am trying to do this via std::this_thread. But when I call funtion timerss() in MyForm.cpp I get error E0245 "Nonstatic member reference must be relative to specific object". I`m beginner in this then can you show me solving of problem step by step if solving is difficult?

timer.hpp

#pragma once
#ifndef TIMERHPP
#define TIMERHPP
#include <chrono>
#include <functional>
class Timerr {
public:
    Timerr();
    void add(std::chrono::milliseconds delay,
        std::function<void()> callback,
        bool asynchronous = true);
};
#endif

timer.cpp

// timer.cpp
#include "timer.hpp"

#include <thread>

Timerr::Timerr() {
}

void Timerr::add(std::chrono::milliseconds delay,
    std::function<void()> callback,
    bool asynchronous) {
    if (asynchronous) {
        std::thread([=]() {
            std::this_thread::sleep_for(std::chrono::milliseconds(delay));
            callback();
            }).detach();
    }
    else {
        std::this_thread::sleep_for(std::chrono::milliseconds(delay));
        callback();
    }
}

Function call(MyForm.cpp):

#include "MyForm.h"
#include <Windows.h>
#include "timer.hpp"
#include <iostream>

using namespace Client; 

void foo()
{
    Client::MyForm::timerss();//E0245 "Nonstatic member reference must be relative to specific object"
}

int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int) {
    Timerr timer;
    timer.add(std::chrono::milliseconds(500), foo);

    Application::EnableVisualStyles();
    Application::SetCompatibleTextRenderingDefault(false);
    Application::Run(gcnew MyForm);
    return 0;
}

MyForm.h

public: void timerss()
{
    timers(1);
}

Solution

  • In namespace:

    using namespace System;
    using namespace System::Threading;
    

    Initialize Component:

    public: MyForm(void)
    {
                InitializeComponent();
    
                SetTimeThread = gcnew Thread(gcnew ThreadStart(this, &MyForm::SetTime)); //added
                SetTimeThread->IsBackground = true; //added
                SetTimeThread->Start(); //added
    }
    

    In the end of class MyForm

    void SetTime() {
                while (true) {
                    if (this->InvokeRequired) {
                        this->Invoke(gcnew Action(this, &MyForm::timerss));// Instead timerss - your method
                    }
                    Thread::Sleep(30*1000);
                }
            }
    private:  System::Threading::Thread^ SetTimeThread;