在阅读了Eli Bendersky 关于通过Python协同程序实现状态机的文章后,我想......
我成功完成了第一部分(但是没有使用async defs或yield froms,我基本上只是移植了代码 - 所以任何改进都是最受欢迎的).
但是我需要一些关于协同程序类型注释的帮助:
#!/usr/bin/env python3
from typing import Callable, Generator
def unwrap_protocol(header: int=0x61,
footer: int=0x62,
dle: int=0xAB,
after_dle_func: Callable[[int], int]=lambda x: x,
target: Generator=None) -> Generator:
""" Simplified protocol unwrapping co-routine."""
#
# Outer loop looking for a frame header
#
while True:
byte = (yield)
frame = [] # type: List[int]
if byte == header:
#
# Capture the full frame
# …Run Code Online (Sandbox Code Playgroud) 我试图阅读有关在调用,暂停,恢复和终止协程函数时调用的操作顺序的文档(功能部件本身的cppreference和标准文档)。该文档深入概述了各种扩展点,这些扩展点允许库开发人员使用库组件自定义协程的行为。从高级的角度来看,这种语言功能似乎是经过深思熟虑的。
不幸的是,我在遵循协程执行机制方面确实很难,而且作为图书馆开发人员,我如何使用各种扩展点来定制所述协程的执行。甚至从哪里开始。
我不完全了解的新定制点集中包含以下功能:
initial_suspend()return_void()return_value()await_ready()await_suspend()await_resume()final_suspend()unhandled_exception()有人可以在高级伪代码中描述运行用户协程时编译器生成的代码吗?在抽象的层面,我想弄清楚的时候功能,如await_suspend,await_resume,await_ready,await_transform,return_value,等叫,他们所服务的目的是什么,我怎么可以用它们来写协同程序库。
不确定这是否是题外话,但是这里的一些入门资源对于整个社区来说都是非常有用的。像在cppcoro中一样四处搜寻并深入研究库实现并不能帮助我克服最初的障碍:(
请考虑以下代码.
std::vector<result_data> do_processing()
{
pqxx::result input_data = get_data_from_database();
return process_data(input_data);
}
std::vector<result_data> process_data(pqxx::result const & input_data)
{
std::vector<result_data> ret;
pqxx::result::const_iterator row;
for (row = input_data.begin(); row != inpupt_data.end(); ++row)
{
// somehow populate output vector
}
return ret;
}
Run Code Online (Sandbox Code Playgroud)
当我在考虑是否可以期待返回值优化(RVO)时,我发现Jerry Coffin的这个答案 [强调我的]:
至少IMO,这通常是一个糟糕的主意,但不是出于效率原因.这是一个糟糕的主意,因为有问题的函数通常应该写成通过迭代器生成输出的通用算法.几乎任何接受或返回容器而不是在迭代器上运行的代码都应该被认为是可疑的.
不要误解我的意思:有时候传递类似于集合的对象(例如字符串)是有意义的,但对于引用的例子,我会考虑传递或返回向量一个糟糕的想法.
有一些Python背景,我非常喜欢Generators.实际上,如果它是Python,我会把上面的函数写成一个Generator,即避免在其他任何事情发生之前处理整个数据的必要性.例如这样:
def process_data(input_data):
for item in input_data:
# somehow process items
yield result_data
Run Code Online (Sandbox Code Playgroud)
如果我正确地解释了Jerry Coffins的说法,这就是他的建议,不是吗?如果是这样,我如何在C++中实现它?
问题是:为什么不继续(在Ruby中)和coroutines(在Python中)更广泛地用于Web编程?
由于在请求之间保持状态的问题使得服务器端web编程变得困难.两个优雅且相关的解决方案是继续(如Scheme,Ruby和Smalltalk中所见)和协同程序(如Python和Go中所见).
Bruce Tate在他的Beyond Java(O'Reilly,2005)中谈到Ruby on Rails和Seaside是Web编程中令人兴奋的新发展.对我而言,Seaside是真正的突破:使用Smalltalk延续,Seaside使编写复杂的请求/响应序列变得非常容易.
我知道在Tornado和Twisted中使用Python协程来减少回调,但与在单个协程中编写视图/控制器来处理一系列HTTP请求以完成在线购买相比,这有点低级别.
我想知道为什么这些看起来如此优秀的想法在Python和Ruby中没有得到更广泛的部署.这只是一种文化问题吗?以这些语言实施的设施限制?或者,在Web开发的背景下,这些方法存在根本缺陷吗?
当不再使用发电机时,应该进行垃圾收集,对吧?我尝试了以下代码,但我不确定哪个部分我错了.
import weakref
import gc
def countdown(n):
while n:
yield n
n-=1
cd = countdown(10)
cdw = weakref.ref(cd)()
print cd.next()
gc.collect()
print cd.next()
gc.collect()
print cdw.next()
Run Code Online (Sandbox Code Playgroud)
在最后一行,我打电话给垃圾收集器,因为没有再打电话cd了.gc应该是自由的cd.但是当我打电话时cdw.next(),它仍然打印8.我再试了几次cdw.next(),它可以成功打印所有其余的,直到StopIteration.
我试过这个是因为我想了解生成器和协同程序是如何工作的.在David Beazley的PyCon演讲"关于协同程序和并发的好奇课程"的幻灯片28中,他说一个协程可以无限期地运行,我们应该用.close()它来关闭它.然后他说垃圾收集器会打电话.close().根据我的理解,一旦我们打电话给.close()自己,gc就会.close()再次打电话.会gc收到警告说它无法调用.close()已经关闭的协程吗?
谢谢你的任何投入.
为了防止上下文切换,我想创建一个大循环来同时服务于网络连接和一些例程.
这是正常功能的实现:
import asyncio
import time
def hello_world(loop):
print('Hello World')
loop.call_later(1, hello_world, loop)
def good_evening(loop):
print('Good Evening')
loop.call_later(1, good_evening, loop)
print('step: asyncio.get_event_loop()')
loop = asyncio.get_event_loop()
print('step: loop.call_soon(hello_world, loop)')
loop.call_soon(hello_world, loop)
print('step: loop.call_soon(good_evening, loop)')
loop.call_soon(good_evening, loop)
try:
# Blocking call interrupted by loop.stop()
print('step: loop.run_forever()')
loop.run_forever()
except KeyboardInterrupt:
pass
finally:
print('step: loop.close()')
loop.close()
Run Code Online (Sandbox Code Playgroud)
这是协同程序的实现:
import asyncio
@asyncio.coroutine
def hello_world():
while True:
yield from asyncio.sleep(1)
print('Hello World')
@asyncio.coroutine
def good_evening():
while True:
yield from asyncio.sleep(1)
print('Good Evening')
print('step: asyncio.get_event_loop()')
loop = asyncio.get_event_loop() …Run Code Online (Sandbox Code Playgroud) 使用channel.close()关闭kotlinx.coroutines通道的原因是什么以及不手动关闭通道的负面影响是什么?如果我不手动关闭频道会有一些不必要的处理?是否会在某个地方引用阻止其成为GCd的频道?或者,关闭功能是否仅作为向渠道的潜在用户通知其不再可以使用的方式存在.
(转自Kotlin论坛的问题https://discuss.kotlinlang.org/t/closing-coroutine-channels/2549)
我是一名从 Java 切换到 Kotlin 的 Android 开发人员,我计划使用协程来处理异步代码,因为它看起来非常有前途。
回到 Java,为了处理异步代码,我使用Executor该类在另一个线程中执行一段耗时的代码,远离 UI 线程。我AppExecutors在我的xxxRepository课程中注入了一个课程来管理一组Executor. 它看起来像这样:
public class AppExecutors
{
private static class DiskIOThreadExecutor implements Executor
{
private final Executor mDiskIO;
public DiskIOThreadExecutor()
{
mDiskIO = Executors.newSingleThreadExecutor();
}
@Override
public void execute(@NonNull Runnable command)
{
mDiskIO.execute(command);
}
}
private static class MainThreadExecutor implements Executor
{
private Handler mainThreadHandler = new Handler(Looper.getMainLooper());
@Override
public void execute(@NonNull Runnable command)
{
mainThreadHandler.post(command);
}
}
private static volatile AppExecutors INSTANCE; …Run Code Online (Sandbox Code Playgroud) 在我学习协程以及如何在 android 应用程序中正确使用它们时,我发现了一些令我感到惊讶的事情。
在启动viewModelScope.launch { }lambda 中使用并设置断点启动协程时,我注意到我的应用程序不再响应,因为它仍在主线程上。
这让我感到困惑,因为文档viewModelScope.launch { }明确指出:
在不阻塞当前线程的情况下启动一个新的协程
当前线程不是主线程吗?如果默认情况下它不在不同的线程上运行,那么启动的全部目的是什么?
我能够viewModelScope.launch(Dispatchers.IO){ }在另一个线程上使用它按我的预期工作,即在另一个线程上运行它。
我试图通过该launch方法完成的是调用存储库并执行一些 IO 工作,即调用 Web 服务并将数据存储在房间数据库中。所以我想调用viewModelScope.launch(Dispatchers.IO){ }在不同的线程上完成所有工作,最后更新 LiveData 结果。
viewModelScope.launch(Dispatchers.IO){
liveData.postValue(someRepository.someWork())
}
所以我的第二个问题是,这是要走的路吗?
multithreading android coroutine android-architecture-components
coroutine ×10
python ×4
generator ×3
kotlin ×3
android ×2
asynchronous ×2
c++ ×2
android-architecture-components ×1
c++20 ×1
go ×1
iterator ×1
java ×1
mypy ×1
python-3.x ×1
ruby ×1