/// <summary> /// Posts a custom message back to the parent thread /// </summary> /// <param name="msg">The custom object to send as the message</param> public void PostMessage(object msg) { if (!WorkerThreadManager.IsWebWorker()) { // Send the result back to the main thread _worker.PostMessage( // Create a new WebWorkerMessage new WorkerThreadManager.WebWorkerMessage { // The message is a finish message MsgType = WorkerThreadManager.MessageTypeMessage, // Set the data to a new WebWorkerFinishMessage Data = msg } ); } else { WorkerThreadManager.PostMessage(msg); } }
/// <summary> /// Start the specified static function in the Web Worker with param passed to the function. /// On completion of the function, it should return a result which is then sent in the main thread to the /// specified onResult callback. /// </summary> /// <param name="entryPoint">The entry point (as a string) representing the function to start in the web worker</param> /// <param name="param">The parameter to be sent to the function when it is started</param> /// <param name="onResult">The callback to be called when the function finishes, callback format is (this thread, the initial parameter, the result from the function)</param> public void Start(string entryPoint, object param, Action <Thread, object, object> onResult = null) { // First we must make sure the function exists and is static object threadStartRef; try { // Try to get a reference to the entry point threadStartRef = WorkerThreadManager.GetObjectRefFromString(Script.Get <object>("window"), entryPoint); // Confirm that it is not null if (threadStartRef == null) { // The reference was null throw new Exception(); } // Confirm that the reference is a function if (!Script.Write <bool>("typeof threadStartRef === 'function'")) { // The reference is not a function throw new Exception(); } } catch (Exception) { // The entry point is not valid, it either does not exist or is not a static function throw new ArgumentException("Thread entry point " + entryPoint + " doesn't seem to exist, or is not a static function"); } // Check that this thread is not already dead if (_isDead) { // Thread is dead, can't start any my functions throw new InvalidOperationException("Attempt made to call Start on a dead thread"); } // Can only run one thread start if there is no on result callback if (onResult == null && _queuedStarts.Any()) { // Whoops throw new InvalidOperationException("Attempt made to queue thread starts with no valid OnResult handler"); } // Ask the worker to start the thread if web workers are available if (_worker != null) { // Ask the worker to start (or queue) this function _worker.PostMessage( // Send a new message new WorkerThreadManager.WebWorkerMessage { // The message is to start a function MsgType = WorkerThreadManager.MessageTypeStart, // The data is a WebWorkerStartMessage Data = new WorkerThreadManager.WebWorkerStartMessage { // Set the thread id ThreadId = _globalThreadIdCounter, // Set the entry point ThreadEntryPoint = entryPoint, // Set the parameter ThreadParam = param } } ); // Add the thread to the queue of thread starts _queuedStarts.Add(_globalThreadIdCounter, // Create a new QueuedThreadStart object new QueuedThreadStart { // Set the thread id ThreadId = _globalThreadIdCounter, // Set the original parameter Param = param, // Set the on result callback OnResult = onResult } ); } else { // Web workers are not available, run the thread start function in this thread // Set the current thread to be the current global thread count _currentThreadId = _globalThreadIdCounter; // Try to call the function try { // Call the function with the parameter, and get the result var result = Script.Write <object>("threadStartRef(param)", threadStartRef, param); // Check if an on result callback was provided if (onResult != null) { // Yes, call the handler with this thread, the original parameter and the result from the message onResult(this, param, result); } else { // No, set the internal result to the result from the message Result = result; } } catch (Exception e) { // An exception occurred running the thread start function // Continue raising the exception in this thread so it is printed to the console throw new Exception("Unhandled exception in thread (" + _currentThreadId + ")", e); } finally { // Always go back to the main thread _currentThreadId = 0; } } // Increment the global thread counter _globalThreadIdCounter++; }