0

Just can't wrap my head around solving this issue, so maybe someone here can enlighten me or maybe even tell me that what I want to achieve isn't possible. :)

Problem statement:

I have an asyncio event loop, on that loop I create a task by supplying my asynchronous coroutine work(). I could then go ahead and cancel the task by invoking its cancel() method - this works. But in my very special case, the asynchronous task itself spawns another operation, which is an underlying blocking / synchronous function.

What happens now, if I decide to cancel the task, is that my asynchronous work() function will be cancelled appropriately, however, the synchronous function is still going to be executed as if nothing ever happened.

I tried to make an example as simple as possible to illustrate my problem:

import asyncio
import time


def sync_work():
    time.sleep(10)
    print("sync work completed")
    return "sync_work_result"


async def work(loop):
    result = await loop.run_in_executor(None, sync_work)
    print(f"sync_work {result}")
    print("work completed")


async def main(loop):
    t1 = loop.create_task(work(loop))
    await asyncio.sleep(4)
    t1.cancel()


loop = asyncio.get_event_loop()
try:
    asyncio.ensure_future(main(loop))
    loop.run_forever()
except KeyboardInterrupt:
    pass
finally:
    print("loop closing")
    loop.close()

This will print out sync work completed after about 10 seconds.

How would I invoke the synchronous function in a way, that would allow me to terminate it once my asynchronous task is cancelled? The tricky part is, that I would not have control over sync_work() as this comes from another external package.

I'm open to other approaches of calling my synchronous function from an asynchronous function that would allow it to be terminated properly in some kind of way.

  • So, you want to run an async func while a sync func is running? – Edher Carbajal Jan 19 '22 at 17:21
  • @EdherCarbajal I want to call a sync function from within an async function, but be able to terminate/cancel both the async function and the sync function at any time, if that makes sense? – user17976448 Jan 19 '22 at 17:25
  • Do you have to use "asyncio" or you're able to use "threading" instead? I'm asking because your sync function blocks the event loop. asyncio is mostly for async callbacks and IO operations, if you're pretending to kill the sync work at any time I guggest to use threading: However let me know if asyncio is needed to find out a way – Edher Carbajal Jan 19 '22 at 18:18
  • What are you really asking for here? If you have a single thread, there is no place for the the command to cancel the currently running function to come from. If you have multiple threads, you can imagine one thread wanting to cancel another. But this is considered a bad practice in any language: https://stackoverflow.com/questions/323972/is-there-any-way-to-kill-a-thread. The asyncio module did not create this limitation with threads, and does not change any of the reasons why killing threads is a bad idea. – Paul Cornelius Jan 20 '22 at 06:06
  • Your case is not special at all, it's the norm. In fact, it is almost impossible to imagine a useful asyncio program that doesn't call synchronous functions. It makes no sense to "cancel" a synchronous function - what line of code gets executed next? When a synchronous function doesn't run to the end, in the best case that is called an "exception" and in the worst case that is called a "crash". – Paul Cornelius Jan 20 '22 at 06:17
  • Please clarify your specific problem or provide additional details to highlight exactly what you need. As it's currently written, it's hard to tell exactly what you're asking. – Community Jan 28 '22 at 15:40

0 Answers0