Q:

How to wait for object to change state

Inside my async handler I want to wait until task's state is changed. For now, I just check the state in an endless loop and wait. Here is an example, the wait_until_done function:
import asyncio

class LongTask:
    state = 'PENDING'

my_task = LongTask()

def done():
    my_task.state = 'DONE'

async def wait_until_done():
    while True:
        if my_task.state == 'PENDING':
            await asyncio.sleep(2)
        else:
            break
    print("Finally, the task is done")

def main(loop, *args, **kwargs):
    asyncio.ensure_future(wait_until_done())
    loop.call_later(delay=5, callback=done)

loop = asyncio.get_event_loop()
main(loop)
loop.run_forever()

Is there a better way for doing that?

A:

Just to avoid confusion: I guess you are not talking about asyncio.Task, but some variable state instead, right?
In this case you have Future and synchronization primitives that allows you to wait some thing changed asynchronously. 
If you need to switch between two states, asyncio.Event is probably what you want. Here's little examle:
import asyncio

my_task = asyncio.Event()

def done():
    my_task.set()

async def wait_until_done():
    await my_task.wait()  # await until event would be .set()
    print("Finally, the task is done")

async def main():
    loop.call_later(delay=5, callback=done)
    await wait_until_done()

loop = asyncio.get_event_loop()
try:
    loop.run_until_complete(main())
finally:
    loop.run_until_complete(loop.shutdown_asyncgens())
    loop.close()

Upd:
More complex example that keeps LongTask interface:
import asyncio

class LongTask:
    _event = asyncio.Event()

    @property
    def state(self):
        return 'PENDING' if not type(self)._event.is_set() else 'DONE'

    @state.setter
    def state(self, val):
        if val == 'PENDING':
            type(self)._event.clear()
        elif val == 'DONE':
            type(self)._event.set()
        else:
            raise ValueError('Bad state value.')

    async def is_done(self):
        return (await type(self)._event.wait())

my_task = LongTask()

def done():
    my_task.state = 'DONE'

async def wait_until_done():
    await my_task.is_done()
    print("Finally, the task is done")

async def main():
    loop.call_later(delay=5, callback=done)
    await wait_until_done()

loop = asyncio.get_event_loop()
try:
    loop.run_until_complete(main())
finally:
    loop.run_until_complete(loop.shutdown_asyncgens())
    loop.close()

