【问题标题】:DiscardAsyncTimer returning before timer callback is completeDiscardAsyncTimer 在计时器回调完成之前返回
【发布时间】:2019-07-07 15:03:37
【问题描述】:

我正在尝试使用异步计时器在 LabWindows/CVI 2017 中编写程序,但遇到了 DiscardAsyncTimer() 函数的问题。来自 DiscardAsyncTimer() 的文档:

创建或丢弃异步计时器的调用将无法完成 (将阻塞)直到所有未完成的异步回调返回。

但是,我遇到了一些内存问题,在调用 DiscardAsyncTimer() 后,我正在释放异步计时器线程中使用的内存。我希望内存不再使用,但显然情况并非如此?我在下面有一个示例程序,它重现了我的问题。运行时,由于试图访问已释放的内存,该程序会生成“一般保护错误”。但是,如果我对文档和文档本身的理解是正确的,那么这应该是不可能的,因为 DiscardAsyncTimer() 应该阻塞,直到所有回调返回。

我的问题:

  1. 我是否正确理解了文档?
  2. 在这个例子中我做了什么蠢事吗?
  3. 我应该如何在释放内存之前验证我的异步计时器线程是否已完成运行?

示例程序:

#include <ansi_c.h>
#include <asynctmr.h>
#include <stdio.h>
#include <utility.h> 
#include <userint.h>


typedef struct {
    int* array;
} MyStruct;

int CVICALLBACK ShuffleValues (int reserved, int timerId, int event, void *callbackData, int eventData1, int eventData2)
{
    if (event == EVENT_TIMER_TICK) {
        printf("start\n");
        MyStruct* mystruct = callbackData;

        // Shuffle values
        for(int i = 0;i < 1000;i++) {
            mystruct->array[0] = mystruct->array[1];
            mystruct->array[1] = mystruct->array[2];
            Delay(0.01);
        }

        printf("finished\n");
    }

    return 0;
}

int main ()
{
    // Allocate memory
    MyStruct* mystruct = malloc(sizeof(MyStruct));
    mystruct->array = malloc(10 * sizeof(int));

    // Start Async Timer
    int timer = NewAsyncTimer(0.01, -1, 1, ShuffleValues, mystruct);

    // Wait a while to let the timer thread run a bit
    Delay(0.5);

    // Destroy Async Timer  
    printf("start destroying\n");
    int retval = DiscardAsyncTimer(timer);
    printf("finished destroying: %d\n", retval);

    // Free memory now that the timer thread is no longer running
    free(mystruct->array);
    free(mystruct);

    Delay(1);
    return 0;
}

一周前我也在 LabWindows/CVI 论坛上问过这个问题,没有任何回应:https://forums.ni.com/t5/LabWindows-CVI/DiscardAsyncTimer-returning-before-timer-callback-is-complete/td-p/3943460

【问题讨论】:

    标签: multithreading labwindows cvi


    【解决方案1】:

    我没有在 NI 论坛上看到您的问题。快速回答是异步计时器在单独的线程中运行,因此您需要采取通常的预防措施。 当错误发生时,您可以通过 [Windows][Threads] 看到它并从一个线程跳转到另一个线程。 使用 volatile 变量进行同步,或者更好的信号量。

    【讨论】:

    • 是的,当然它们在不同的线程中运行。问题是文档指出DiscardAsyncTimer() 阻塞,直到所有未完成的异步计时器线程返回,但这并没有发生。所以你是说文档有问题,所以我必须使用传统的线程内存管理方法?
    • 正确。我已经在更合适的 NI 论坛上回复了(更多的眼球)。
    猜你喜欢
    • 1970-01-01
    • 2019-06-11
    • 2020-04-17
    • 1970-01-01
    • 1970-01-01
    • 2021-05-22
    • 1970-01-01
    • 2021-02-15
    • 1970-01-01
    相关资源
    最近更新 更多