public static NativeCommon.IFabricAsyncOperationContext WrapNativeAsyncMethodImplementation( Func <CancellationToken, Task> func, NativeCommon.IFabricAsyncOperationCallback callback, string functionTag, InteropApi interopApi) { CancellationTokenSource cancellationTokenSource = null; try { AppTrace.TraceSource.WriteNoise(functionTag, "WrapNativeAsyncImpl - Begin"); cancellationTokenSource = new CancellationTokenSource(); Task t = func(cancellationTokenSource.Token); return(new AsyncTaskCallInAdapter(callback, t, interopApi, cancellationTokenSource, functionTag)); } catch (Exception ex) { AppTrace.TraceSource.WriteExceptionAsWarning(functionTag, ex, "WrapNativeAsyncImpl - Begin threw exception"); if (cancellationTokenSource != null) { cancellationTokenSource.Dispose(); } interopApi.HandleException(ex); TryTranslateManagedExceptionToCOMAndThrow(ex); throw; } }
public AsyncTaskCallInAdapter( NativeCommon.IFabricAsyncOperationCallback callback, Task userTask, InteropApi interopApi, CancellationTokenSource cancellationTokenSource = null, string functionTag = null) { Requires.Argument <Task>("task", userTask).NotNull(); Requires.Argument("interopApi", interopApi).NotNull(); this.interopApi = interopApi; this.nativeCallback = callback; this.userTask = userTask; this.cancellationTokenSource = cancellationTokenSource; // CompletedSynchronously is used to identify whether the task is done or not // The AsyncTaskCallInAdapter is usually the last item to be constructed and returned from a BeginXXX function // Thus, if the task is not complete at this point it is executing in a separate thread // and the Completion callback will be called on a separate thread // we have not yet observed whether the user task is complete this.completedSynchronously = (int)CompletedSynchronouslyState.Unknown; // setup the continuation. // if the user task completes before we are able to determine then the callback will set the completed synchronously state // it does not matter whether the continuation is executed on this thread or the thread on which the user task is running this.callbackContinuation = this.userTask.ContinueWith((t) => this.ProcessNativeCallback(), TaskContinuationOptions.ExecuteSynchronously); // if the completedSynchronously state is still unknown then the continuation has not executed as yet which means that it is queued up for execution in a separate thread // thus the completed synchronously should be set to ASync // if on the other hand the continuation has begun executing (and we are still in the BeginXXX method because we are in the constructor) // then CompletedSynchronously would have been set to Synchronous by the continuation Interlocked.CompareExchange(ref this.completedSynchronously, (int)CompletedSynchronouslyState.Asynchronously, (int)CompletedSynchronouslyState.Unknown); this.functionTag = functionTag ?? "AsyncTaskCallInAdapter"; }
public static void WrapNativeSyncMethodImplementation(Action action, string functionTag, InteropApi interopApi) { Utility.WrapNativeSyncMethodImplementation <object>( () => { action(); return(null); }, functionTag, interopApi); }
public static TResult WrapNativeSyncMethodImplementation <TResult>(Func <TResult> func, string functionTag, InteropApi interopApi) { try { AppTrace.TraceSource.WriteNoise(functionTag, "Begin (sync)"); TResult result = func(); AppTrace.TraceSource.WriteNoise(functionTag, "End (sync"); return(result); } catch (Exception ex) { AppTrace.TraceSource.WriteExceptionAsWarning(functionTag, ex, "WrapNativeSyncMethodImplementation failed"); interopApi.HandleException(ex); TryTranslateManagedExceptionToCOMAndThrow(ex); throw; } }