什么是Python等价的TaskCompletionSource <t>(.NET)?

时间:2016-02-10 15:51:47

标签: c# python asynchronous task-parallel-library python-asyncio

我正在尝试实现以下伪代码(部分灵感来自于.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

推荐使用pythonic(或.NET-ish但兼容python)的方法是什么?

3 个答案:

答案 0 :(得分:1)

我尝试以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

代码仍然不是非常pythonic但我希望你能得到我的观点。

答案 1 :(得分:1)

等效的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]

答案 2 :(得分:0)

假设提供者是一个python线程。 您可以使用等待线程竞争的加入(超时)方法或超时。 join()始终返回None,以便检查线程是否仍然存活,您需要使用isAlive()。 这是实现taskCompletion

的一个选项
def taskCompletion(thread,timeout): 
   thread.join(timeout) 
   return isAlive()