Tcl中的异步文件IO

达博

我有一个包装在Tcl中的C函数,该函数可打开文件,读取内容,执行操作并返回值。不幸的是,当我调用该函数打开大文件时,它阻止了事件循环。操作系统是linux。

我想使通话异步。我该怎么做?

(我可以将工作传递给另一个Tcl线程,但这并不是我想要的)。

多纳研究员

通常这很难做到。问题在于,由于操作系统级别涉及抽象,异步文件操作不适用于普通文件。最好的解决方法(如果可以)是首先在文件上建立索引,这样就可以避免通读全部内容,而只读seek到靠近数据的地方。这是数据库工作方式的核心。

如果你不能做到这一点,但你可以应用一个简单的过滤器,把该过滤器在子进程(管道工作,在Tcl的异步I / O,而他们这样做的所有支持的平台上),或者另一个线程(线程间的消息从异步处理的角度来看也很不错)可以创造奇迹。

如果可以,请使用上述技术。他们是我认为您应该做的。

如果那是不切实际的,那么您将不得不采用困难的方式进行此操作。困难的方法涉及在处理中插入事件循环感知延迟。

引入8.5及更低版本的延迟

在Tcl 8.5及更高版本中,您可以通过以下步骤将代码分成不同的过程,并使用这样的节通过“延迟”在它们之间传递控制权:

# 100ms delay, but tune it yourself
after 100 [list theNextProcedure $oneArgument $another]

这是延续传递的风格,正确行事可能很棘手。特别是,它对复杂的处理相当混乱。例如,假设您正在文件的前几千行循环:

proc applyToLines {filename limit callback} {
    set f [open $filename]
    for {set i 1} {$i <= $limit} {incr i} {
        set line [gets $f]
        if {[eof $f]} break
        $callback $i $line
    }
    close $f
}
applyToLines "/the/filename.txt" 1000 DoSomething

在经典的Tcl CPS中,您可以这样做:

proc applyToLines {filename limit callback} {
    set f [open $filename]
    Do1Line $f 1 $limit $callback
}
proc Do1Line {f i limit callback} {
    set line [gets $f]
    if {![eof $f]} {
        $callback $i $line
        if {[incr i] <= $limit} {
            after 10 [list Do1Line $f $i $limit $callback]
            return
        }
    }
    close $f
}
applyToLines "/the/filename.txt" 1000 DoSomething

如您所见,这不是一个简单的转换,并且如果您希望在处理完成后执行某项操作,则需要传递一个回调。(您也可以使用全局变量,但这并不优雅……)

(如果您需要帮助来更改代码以使其正常工作,则需要向我们展示您需要帮助的代码。)

在8.6中引入延迟

在Tcl 8.6中,尽管上述代码技术仍然可以使用,但是您还有另一个选择:协程!我们可以这样写:

proc applyToLines {filename limit callback} {
    set f [open $filename]
    for {set i 1} {$i <= $limit} {incr i} {
        set line [gets $f]
        if {[eof $f]} break
        yield [after 10 [info coroutine]]
        $callback $i $line
    }
    close $f
}
coroutine ApplyToAFile applyToLines "/the/filename.txt" 1000 DoSomething

这是几乎相同的,除了用线yieldinfo coroutine(其暂停协程,直到它从在10ms左右的时间事件循环恢复),并用线coroutine ApplyToAFile,其中该前缀创建一个协程(给定任意名称ApplyToAFile),并将其设置跑步。如您所见,像这样转换您的代码并不难。

协程引擎完全没有机会移植到8.5或更早版本;它完全需要8.6中的非递归脚本执行引擎。)

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

C ++中的真正异步文件IO

来自分类Dev

TCL中的FIFO文件

来自分类Dev

在TCL中写入文件

来自分类Dev

忽略文件TCL中的行

来自分类Dev

复制并替换tcl中的文件

来自分类Dev

如何从非tcl线程异步调用Tcl线程中的命令?

来自分类Dev

IO异步方法中TaskCompletionSource的用法

来自分类Dev

异步IO中实际发生的情况

来自分类Dev

.Net文件IO-如何异步读取文件创建日期

来自分类Dev

Python中的异步文件下载

来自分类Dev

在Powershell中异步移动文件

来自分类Dev

使用内部变量在Tcl中打开文件

来自分类Dev

需要在TCL中容纳多个文件

来自分类Dev

在Windows上的TCL中创建文件

来自分类Dev

Java中的文件io

来自分类Dev

使用文件时,scala是否提供异步非阻塞IO?

来自分类Dev

使用 TCL 中的文件属性授予文件权限

来自分类Dev

如何从TCL中的文件中获取选择性数据?

来自分类Dev

从文件中拆分一行以替换tcl中的元素

来自分类Dev

复制然后在Bash中异步移动文件

来自分类Dev

在C ++ UNIX中异步写入文件

来自分类Dev

在Delphi中异步附加到.txt文件

来自分类Dev

C#中的异步下载文件

来自分类Dev

异步读取 mocha 测试中的文件?

来自分类Dev

等待功能,直到在python异步IO中收到回调

来自分类Dev

在 Task.Run 中包装 IO 绑定的异步方法

来自分类Dev

如果tcl代码仍在写入,是否可以读取tcl中的文件?

来自分类Dev

TCL-REGEX ::如何使用TCL regexp过滤文本文件中多次出现的行

来自分类Dev

如果tcl代码仍在写入,是否可以读取tcl中的文件?