简体   繁体   English

Python相当于TaskCompletionSource的情况 <T> (。净)?

[英]What would be a Python equivalent of TaskCompletionSource<T> (.NET)?

I am trying to implement the following pseudo-code (partly inspired from what would be possible with the TaskCompletionSource<T> in .NET), where the objective is to wait for a particular event to be received to continue execution (or throw a TimeoutError ): 我正在尝试实现以下伪代码(部分受.NET中TaskCompletionSource<T>启发),其目的是等待接收到特定事件以继续执行(或引发TimeoutError ):

from axel import Event

def _wait_for_provider_up(self, data_provider: Provider, ms_timeout: int) -> bool:
    if provider.State == ProviderState.Connected: return True
    if provider.State == ProviderState.Faulted: return False
    taskCompletion = TaskCompletionSource<bool>()

    def onStateChanged(sender, e: ProviderStateChangedEventArgs):
        if e.State == ProviderState.Connected:
            taskCompletion.TrySetResult(True)
        elif e.State == ProviderState.Faulted:
            taskCompletion.TrySetResult(False)

    provider.StateChanged += onStateChanged
    try:
        if provider.State == ProviderState.Connected: return True
        elif provider.State == ProviderState.Faulted: return False
        if not taskCompletion.Task.Wait(ms_timeout) or not taskCompletion.Task.Result or provider.State != ProviderState.Connected:
            return False
    finally:
        provider.StateChanged -= onStateChanged
    return True

What would be a recommended pythonic (or .NET-ish but python-compatible) way to achieve that? 什么是推荐的pythonic(或.NET风格但与python兼容)的方法来实现这一目标?

I've tried to rewrite your code in asyncio way but please pay attention: function _wait_for_provider_up has been changed to coroutine : 我试图以asyncio方式重写您的代码,但请注意: _wait_for_provider_up函数已更改为coroutine

from axel import Event

async def _wait_for_provider_up(self, data_provider: Provider, ms_timeout: int) -> bool:
    if provider.State == ProviderState.Connected: 
        return True
    if provider.State == ProviderState.Faulted: 
        return False
    taskCompletion = asyncio.Future()

    def onStateChanged(sender, e: ProviderStateChangedEventArgs):
        if e.State == ProviderState.Connected:
            taskCompletion.set_result(True)
        elif e.State == ProviderState.Faulted:
            taskCompletion.set_result(False)

    provider.StateChanged += onStateChanged
    try:
        if provider.State == ProviderState.Connected: 
            return True
        elif provider.State == ProviderState.Faulted: 
            return False
        try:
            result = await asyncio.wait_for(taskCompletion, timeout=ms_timeout/1000)
            if not result or provider.State != ProviderState.Connected:
                return False
        except asyncio.TimeoutError:
            return False  
    finally:
        provider.StateChanged -= onStateChanged
    return True

The code is still not very pythonic but I hope you'll get my point. 该代码仍然不是很Python,但是希望您能理解我的意思。

The python equivalent is asyncio.Future . python等效项是asyncio.Future

import asyncio
source = asyncio.Future()

async def await_concat(x):
    return x + await source


async def set_after_two_seconds():
    print("READY")
    await asyncio.sleep(2)
    print("SET")
    source.set_result("GO")

print(asyncio.get_event_loop().run_until_complete(asyncio.gather(
    await_concat("PASS "),
    set_after_two_seconds(),
)))

## prints
# READY
## (note: two second pause here)
# SET
# ['PASS GO', None]

Assuming the provider is a python thread. 假设提供者是python线程。 You can use the join(timeout) method which waits for the thread to compete or the timeout. 您可以使用join(timeout)方法,该方法等待线程竞争或超时。 join() always returns None so to check if the thread is still alive you need to use isAlive(). join()始终返回None,因此要检查线程是否仍在运行,您需要使用isAlive()。 Here is one option in implementing the taskCompletion 这是实现taskCompletion的一种选择

def taskCompletion(thread,timeout): 
   thread.join(timeout) 
   return isAlive()  

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

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