简体   繁体   English

使用 ib_insync 进行多线程和异步执行

[英]Multithreading and async execution with ib_insync

I am facing a perplexing problem when implementing multi-threading with ib_insync.在使用 ib_insync 实现多线程时,我面临一个令人困惑的问题。 My knowledge of both multithreading and asynchronous programming is surely insufficient to solve this.我对多线程和异步编程的了解肯定不足以解决这个问题。 Interestingly, the roadblock is only with the ib.sleep command and other functions seem to be working just fine.有趣的是,障碍仅与 ib.sleep 命令有关,而其他功能似乎运行良好。

Below are two scenarios - one without multi-threading and one with.下面是两种情况 - 一种没有多线程,一种有。 Without multi-threading everything works fine, but when multi-threading is used to run parallelly, I get the following warning and the code stops.如果没有多线程,一切正常,但是当使用多线程并行运行时,我收到以下警告并且代码停止。

RuntimeWarning: coroutine 'sleep' was never awaited

What am I missing?我错过了什么? I understand ib.sleep is a coroutine and needs to be awaited within an async function, but I do not understand how it works when called directly but only fails within a thread.我知道 ib.sleep 是一个协程,需要在异步函数中等待,但我不明白直接调用时它是如何工作的,但仅在线程内失败。 What is the best way to implement this correctly?正确执行此操作的最佳方法是什么?

from ib_insync import * 
from concurrent.futures import ThreadPoolExecutor 
import random 
import nest_asyncio 
nest_asyncio.apply()
    
# Define IB object 
ib = IB()
    
# Connect to IB 
ib.connect('127.0.0.1', 7497, clientId=131)
    
# Define sample function with ib.sleep 
def sample_function(sleep_time):
    print('Sleeping now') 
    ib.sleep(sleep_time)
    print('Sleep completed!')
    
# Call function directly - works fine
sample_function()
    
# Run multiple threads and call function within each thread - RunTimeWarning and stops
executor = ThreadPoolExecutor(max_workers=2) 
executor.submit(sample_function, random.randint(1,20)) 
executor.submit(sample_function, random.randint(1,20))

Edit: The use case I am trying to solve for is to call a function parallelly with different parameters.编辑:我试图解决的用例是使用不同的参数并行调用一个函数。 Edited the sample code above accordingly.相应地编辑了上面的示例代码。 The catch here is ib_insync is an asynchronous implementation based on asyncio, so running multiple threads fails.这里的问题是 ib_insync 是基于 asyncio 的异步实现,因此运行多个线程会失败。

The function doesn't work fine in either case, it just happens that in the main thread the warning is not shown.该函数在任何一种情况下都无法正常工作,只是在主线程中未显示警告。 RuntimeWarning on non-awaited coroutines is provided on a best-effort basis without a guarantee that it will be emitted in all circumstances.非等待协程上的RuntimeWarning是在尽力而为的基础上提供的,但不保证在所有情况下都会发出。

To fix the issue, you should avoid mixing threads and asyncio in the first place.要解决此问题,您应该首先避免混合线程和 asyncio。 For example, if you need to run several coroutines in parallel, you can spawn them as tasks using asyncio.crate_task , and then await some or all of them.例如,如果您需要并行运行多个协程,您可以使用asyncio.crate_task它们生成为任务,然后等待其中的一些或全部。 Or you can use the asyncio.gather utility function which does it for you:或者您可以使用asyncio.gather实用程序功能为您完成此操作:

result1, result2, ... = await asyncio.gather(coro1(), coro2(), ...)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM