2

I'm using django channels in order to send multiple responses to a single request. The code is something like this:

class terminal(WebsocketConsumer):
   def connect(self):
       self.accept()

   def disconnect(self, close_code):
       self.close()

   def receive(self, text_data):
       data_json = json.loads(text_data)
       if data_json['event'] == 'initial':
          self.t = threading.Thread(target=self.send_data)
          self.t.daemon = True
          self.t.start()
       elif data_json['event'] == 'pause':
          pass
       print("done")

   def send_data(self):
       n = 100
       end = 1000000
       while (n + 1 < end)
          # some code
          self.send(json.dumps({'data':data})
          n += 1

I've used thread to be able to listen to pause and other events while data is being sent to the client. The problem is that the thread keeps running after websocket gets disconnected.

Is there a way to kill a python thread in disconnect function? Or maybe a better way to implement this?

Parham.rm
  • 133
  • 7
  • killing python threads is not easy, if your thread has a while tool what you can do is set some flag that the thread checks on each iteration round the run loop. see: https://stackoverflow.com/questions/323972/is-there-any-way-to-kill-a-thread – Matthaus Woolard Nov 07 '18 at 13:47
  • 1
    i would suggest instread of opeing a thread you create a child async runloop. this can be killed more cleanly and will play with the rest of the async nature of channels better. – Matthaus Woolard Nov 07 '18 at 13:49

1 Answers1

1

There are probably many ways to solve your problem. I would suggest, you use the function sync_to_async() from asgiref.sync. It creates a new thread and "awaits", until it is finished. "awaits" means, that in an async context, other code can run in the meantime.

To call sync_to_async() you have to use a AsyncWebsocketConsumer

class terminal(AsyncWebsocketConsumer):
   async def connect(self):
       awaitself.accept()

   async def disconnect(self, close_code):
       await self.close()

   async def receive(self, text_data):
       data_json = json.loads(text_data)
       if data_json['event'] == 'initial':
          await sync_to_async(self.send_data)()
       elif data_json['event'] == 'pause':
          pass
       print("done")

   def send_data(self):
       n = 100
       end = 1000000
       while (n + 1 < end)
          # some code
          sync_to_async(self.send)(json.dumps({'data':data})
          n += 1
ostcar
  • 161
  • 4