Python асинхронные обратные вызовы и генераторы

Это могло произойти на serverSocket.Stop(). Который я назвал каждый раз, когда Dispose был назван.

Вот то, как моя обработка исключений для слушать потока была похожа:

try
{
    //...
}
catch (SocketException socketEx)
{    
    if (_disposed)
        ar.SetAsCompleted(null, false); //exception because listener stopped (disposed), ignore exception
    else
        ar.SetAsCompleted(socketEx, false);
}

Теперь то, что произошло, было, время от времени исключение произойдет, прежде _disposed имел значение true. Таким образом, решение для меня состояло в том, чтобы сделать все ориентированным на многопотоковое исполнение.

10
задан Cristian Ciupitu 20 July 2014 в 21:17
поделиться

3 ответа

Есть несколько способов мультиплексирования задач. Мы не можем сказать, что лучше всего подходит для вашего случая, не зная, что вы делаете. Наверное, самый простой / универсальный способ - использовать потоки. Взгляните на этот вопрос , чтобы получить некоторые идеи.

2
ответ дан 3 December 2019 в 23:13
поделиться

UPDATE: возьмите это с зерном соли, так как я не соприкасаюсь с современными разработками питоновой асинхроники, включая gevent и asyncio и на самом деле не имею серьезного опыта работы с асинхронным кодом.


На Python существует 3 общих подхода к беспоточному асинкодированию:

  1. Callbacks - уродливое, но работающее, Twisted делает это хорошо.

  2. Генераторы - мило, но требуют всего вашего кода, чтобы следовать стилю.

  3. Используйте реализацию на Python с реальными таблеточками - Stackless (RIP) и greenlet.

К сожалению, в идеале вся программа должна использовать один стиль, иначе все усложнится. Если вы не против, чтобы ваша библиотека открывала полностью синхронный интерфейс, то, скорее всего, вы не против, но если вы хотите, чтобы несколько вызовов вашей библиотеки работали параллельно, особенно параллельно с асинхронным кодом другим , то вам нужно общее событие "реактор", который может работать со всем кодом.

Так что если у вас есть (или вы ожидаете, что у пользователя будет) другой асинхронный код в приложении, то принятие той же модели, скорее всего, умно.

Если же вы не хотите понимать весь этот беспорядок, то подумайте об использовании плохих старых нитей. Они тоже уродливы, но работают со всем остальным.

Если вы хотите понять, как могут помочь вам coroutines - и как они могут усложнить вам жизнь, то Курс Дэвида Бизли "A Curious Course on Coroutines and Concurrency" - это хороший материал.

Гринлеты могут быть самым чистым способом, если вы можете использовать расширение. У меня нет с ними никакого опыта, так что не могу сказать многого.

10
ответ дан 3 December 2019 в 23:13
поделиться

Нужно сделать функцию foo тоже асинхронной. Как насчет такого подхода?

@make_async
def foo(somearg, callback):
    # This function is now async. Expect a callback argument.
    ...

    # change 
    #       x = sync_call1(somearg, some_other_arg)
    # to the following:
    x = yield async_call1, somearg, some_other_arg
    ...

    # same transformation again
    y = yield async_call2, x
    ...

    # change
    #     return bar
    # to a callback call
    callback(bar)

А make_async можно определить так:

def make_async(f):
    """Decorator to convert sync function to async
    using the above mentioned transformations"""
    def g(*a, **kw):
        async_call(f(*a, **kw))
    return g

def async_call(it, value=None):
    # This function is the core of async transformation.

    try: 
        # send the current value to the iterator and
        # expect function to call and args to pass to it
        x = it.send(value)
    except StopIteration:
        return

    func = x[0]
    args = list(x[1:])

    # define callback and append it to args
    # (assuming that callback is always the last argument)

    callback = lambda new_value: async_call(it, new_value)
    args.append(callback)

    func(*args)

ВНИМАНИЕ: Я не тестировал этот

.
2
ответ дан 3 December 2019 в 23:13
поделиться
Другие вопросы по тегам:

Похожие вопросы: