class CliEventLoopManager(object): """Manage the main event loop using .NET threads. For the time being, this implementation is pretty light and mostly relies on .NET async doing "the right thing(tm)" with a sprinkle of threading here and there. """ def __init__(self): self._init_cancellation() self._disconnect_event = ManualResetEventSlim(False) def _init_cancellation(self): """Initialize the cancellation source and token.""" self.cancellation_token_source = CancellationTokenSource() self.cancellation_token = self.cancellation_token_source.Token self.cancellation_token.Register( lambda: LOGGER.debug('Started token cancelation')) def run_forever(self): """Kick-starts a blocking loop while the ROS client is connected.""" self._disconnect_event.Wait(self.cancellation_token) LOGGER.debug('Received disconnect event on main loop') def call_later(self, delay, callback): """Call the given function after a certain period of time has passed. Args: delay (:obj:`int`): Number of seconds to wait before invoking the callback. callback (:obj:`callable`): Callable function to be invoked when the delay has elapsed. """ # NOTE: Maybe there's a more elegant way of doing this def closure(): Thread.Sleep(delay * 1000) callback() Task.Factory.StartNew(closure, self.cancellation_token) def call_in_thread(self, callback): """Call the given function on a thread. Args: callback (:obj:`callable`): Callable function to be invoked in a thread. """ Task.Factory.StartNew(callback, self.cancellation_token) def terminate(self): """Signals the termination of the main event loop.""" self._disconnect_event.Set() if self.cancellation_token_source: self.cancellation_token_source.Cancel() # Renew to allow re-connects self._init_cancellation()
def __init__(self, host='127.0.0.1', port=9000): """init the client, wait until it successfully connected to server""" scheme = 'ws' builder = UriBuilder(scheme, host, port) uri = builder.Uri self.token = CancellationTokenSource().Token self.socket = ClientWebSocket() task = self.socket.ConnectAsync(uri, self.token) task.Wait() print('connected to cloud using .NET client!')
def _init_cancellation(self): """Initialize the cancellation source and token.""" self.cancellation_token_source = CancellationTokenSource() self.cancellation_token = self.cancellation_token_source.Token self.cancellation_token.Register( lambda: LOGGER.debug('Started token cancelation'))
class CliEventLoopManager(object): """Manage the main event loop using .NET threads. For the time being, this implementation is pretty light and mostly relies on .NET async doing "the right thing(tm)" with a sprinkle of threading here and there. """ def __init__(self): self._init_cancellation() self._disconnect_event = ManualResetEventSlim(False) def _init_cancellation(self): """Initialize the cancellation source and token.""" self.cancellation_token_source = CancellationTokenSource() self.cancellation_token = self.cancellation_token_source.Token self.cancellation_token.Register( lambda: LOGGER.debug('Started token cancellation')) def run(self): """Kick-starts a non-blocking event loop. In this implementation, this is a no-op.""" pass def run_forever(self): """Kick-starts a blocking loop while the ROS client is connected.""" self._disconnect_event.Wait(self.cancellation_token) LOGGER.debug('Received disconnect event on main loop') def call_later(self, delay, callback): """Call the given function after a certain period of time has passed. Args: delay (:obj:`int`): Number of seconds to wait before invoking the callback. callback (:obj:`callable`): Callable function to be invoked when the delay has elapsed. """ # NOTE: Maybe there's a more elegant way of doing this def closure(): Thread.Sleep(delay * 1000) callback() Task.Factory.StartNew(closure, self.cancellation_token) def call_in_thread(self, callback): """Call the given function on a thread. Args: callback (:obj:`callable`): Callable function to be invoked in a thread. """ Task.Factory.StartNew(callback, self.cancellation_token) def blocking_call_from_thread(self, callback, timeout): """Call the given function from a thread, and wait for the result synchronously for as long as the timeout will allow. Args: callback: Callable function to be invoked from the thread. timeout (:obj: int): Number of seconds to wait for the response before raising an exception. Returns: The results from the callback, or a timeout exception. """ manual_event = ManualResetEventSlim(False) result_placeholder = {'manual_event': manual_event} ThreadPool.QueueUserWorkItem(WaitCallback(callback), result_placeholder) # Wait with timeout results bool indicating success/failure if timeout and manual_event.Wait(timeout * 1000, self.cancellation_token): return result_placeholder # Wait without timeouts raises in case of failure triggered by cancellation if not timeout: manual_event.Wait(self.cancellation_token) return result_placeholder self.raise_timeout_exception() def raise_timeout_exception(self, _result=None, _timeout=None): """Callback called on timeout. Args: _result: Unused--required by Twister. _timeout: Unused--required by Twister. Raises: An exception. """ raise Exception('No service response received') def get_inner_callback(self, result_placeholder): """Get the callback which, when called, provides result_placeholder with the result. Args: result_placeholder: (:obj: dict): Object in which to store the result. Returns: A callable which provides result_placeholder with the result in the case of success. """ def inner_callback(result): result_placeholder['result'] = result result_placeholder['manual_event'].Set() return inner_callback def get_inner_errback(self, result_placeholder): """Get the errback which, when called, provides result_placeholder with the error. Args: result_placeholder: (:obj: dict): Object in which to store the result. Returns: A callable which provides result_placeholder with the error in the case of failure. """ def inner_errback(error): result_placeholder['exception'] = error result_placeholder['manual_event'].Set() return inner_errback def terminate(self): """Signals the termination of the main event loop.""" self._disconnect_event.Set() if self.cancellation_token_source: self.cancellation_token_source.Cancel() # Renew to allow re-connects self._init_cancellation()
from System.Threading import CancellationTokenSource from threading import Event from Basic import async ThreadControls=[] numberOfThreads = 4 for i in range(numberOfThreads): ThreadControls.append([Event(),CancellationTokenSource()]) # use in code wherever you want to allow pausing or cancelling of face thread, you might place that line in every other line of your code :) def pause_and_cancel_point(ThreadID): ThreadControls[ThreadID][0].wait() ThreadControls[ThreadID][1].Token.ThrowIfCancellationRequested() # to abort thread def cancel(ThreadID): print('Cancelling thread '+ str(ThreadID)+'.') ThreadControls[ThreadID][1].Cancel() # to pause thread def pause(ThreadID): print('Pausing thread '+ str(ThreadID)+'.') ThreadControls[ThreadID][0].clear() # to resume thread def resume(ThreadID): print('Resuming thread '+ str(ThreadID)+'.') ThreadControls[ThreadID][0].set()