sogou / workflow

C++ Parallel Computing and Asynchronous Networking Framework
Apache License 2.0
13.07k stars 2.41k forks source link

series串行执行的问题 #1607

Closed HT-Sun closed 1 month ago

HT-Sun commented 2 months ago

我的需求:

  1. 我占用主线程监控按键事件,不同的按键事件会触发不同的任务,对应不同的series。
  2. 在实际使用过程中,我会在短时间内顺序按下多个按键,由于主线程一直在监控所以会对应生成一系列的serieswork。这些任务执行所需的时间又是不同的,所以serieswork结束触发回调的时间可能和按键的顺序不同。但是我又想要让这些serieswork最终的回调函数是按照最初的按键触发顺序来执行。

我的疑问:

  1. 对于上述需求在workflow框架下可以通过什么方式实现。
  2. 如何不占用线程的监控按键事件(目前监控按键事件是通过cv.waitKey(...)的方式)。

我尝试采用WFMessageQueue,但是无法进入任务的回调,代码如下:

IMTask *task = IMFactory::create_thread_task("press", empty, callback);
// tast input initialize
// ...

WFConditional *cond = queue.get(task);
SeriesWork *series = Workflow::create_series_work(cond, [&queue](const SeriesWork *work) {
    queue.post(nullptr);
});

// series context initialize
// ...

series->start();

其中empty是一个空的过程。

Barenboim commented 2 months ago

你的例子应该是WFResourcePool,原始需要一个资源。WFMessageQueue的话初始任务就没有人唤醒啊,当然没有一个任务可以启动。

让series回调顺序执行的需求挺奇怪的,任务都是异步的,按顺序回调的目的是什么呢。

HT-Sun commented 2 months ago

我在尝试用workflow来改写games101课程作业中提供的代码。在series的回调过程中会将光栅器中的数据进行可视化。 我最初的想法是,在短时间内触发多个按键事件,让光栅化过程异步,将可视化过程集中一起按照按键事件触发的顺序依次可视化处理,以此提升程序的性能。

但是,就我实际使用过程,发现画面帧率确实提升了,但是会出现一点延迟TAT。

并且我在使用WFResourcePool的过程中发现一个问题。我在使用pool的过程中,如果有series持有资源但是任务还没有完成,尚未放回资源,但是这个时候主线程由于检测到退出程序的按键而提前退出了,这是不是会导致异常。

Barenboim commented 2 months ago

不太清楚game101这个作业的内容,但是你把一些异步处理的事件又做了一次按顺序的操作,如果处理不好应该是会有延迟的。我也想一想你说的这个异步转顺序的问题,能不能抽象成一种模式。

WFResourcePool的问题,关于程序退出,我们有一个文档有详细描述。最好的办法还是等所有任务运行到callback,程序再退。如果main函数可以提前结束,你可能需要检查一些任务的结束状态,避免再发起新任务。可以看一下这个文档: https://github.com/sogou/workflow/blob/master/docs/about-exit.md

HT-Sun commented 2 months ago

还有一个问题是,我如何不占用线程的监控按键事件。我当前采用的是在主循环里进行死循环。

int main()
{
    while(true)
    {
        key = cv.waitkey(10);
        if(key ==27) return;
        if(key =='a') IMTask = IMFactory::create_thread_task(....);
    }
}
Barenboim commented 2 months ago

还有一个问题是,我如何不占用线程的监控按键事件。我当前采用的是在主循环里进行死循环。

int main()
{
    while(true)
    {
        key = cv.waitkey(10);
        if(key ==27) return;
        if(key =='a') IMTask = IMFactory::create_thread_task(....);
    }
}

这个要异步接收,可能和设备的接口有关系了。你需要研究一下底层原理,然后从SubTask类开始派生。

关键这个还是一个被动任务,所以还需要实现一个类似CommService的服务类用于产生任务。完整的做出来不是很简单。