/// <summary> /// Starts this <see cref="MicroThread"/> with the specified function. /// </summary> /// <param name="microThreadFunction">The micro thread function.</param> /// <param name="flags">The flags.</param> /// <param name="scheduleMode">The schedule mode.</param> /// <exception cref="System.InvalidOperationException">MicroThread was already started before.</exception> public void Start(Func<Task> microThreadFunction, ScheduleMode scheduleMode = ScheduleMode.Last) { ScriptId = microThreadFunction.Target.GetType().Name; // TODO: Interlocked compare exchange? if (Interlocked.CompareExchange(ref state, (int)MicroThreadState.Starting, (int)MicroThreadState.None) != (int)MicroThreadState.None) throw new InvalidOperationException("MicroThread was already started before."); Action wrappedMicroThreadFunction = async () => { try { State = MicroThreadState.Running; await microThreadFunction(); if (State != MicroThreadState.Running) throw new InvalidOperationException("MicroThread completed in an invalid state."); State = MicroThreadState.Completed; } catch (OperationCanceledException e) { // Exit gracefully on cancellation exceptions SetException(e); } catch (Exception e) { Scheduler.Log.Error("Unexpected exception while executing a micro-thread. Reason: {0}", new object[] {e}); SetException(e); } finally { lock (Scheduler.allMicroThreads) { Scheduler.allMicroThreads.Remove(AllLinkedListNode); } } }; Action callback = () => { SynchronizationContext = new MicroThreadSynchronizationContext(this); SynchronizationContext.SetSynchronizationContext(SynchronizationContext); wrappedMicroThreadFunction(); }; lock (Scheduler.allMicroThreads) { Scheduler.allMicroThreads.AddLast(AllLinkedListNode); } ScheduleContinuation(scheduleMode, callback); }