/* Returns the exception thrown when invoking, if any */ static MonoObject * mono_async_invoke (ThreadPool *tp, MonoAsyncResult *ares) { ASyncCall *ac = (ASyncCall *)ares->object_data; MonoObject *res, *exc = NULL; MonoArray *out_args = NULL; HANDLE wait_event = NULL; if (ares->execution_context) { /* use captured ExecutionContext (if available) */ MONO_OBJECT_SETREF (ares, original_context, mono_thread_get_execution_context ()); mono_thread_set_execution_context (ares->execution_context); } else { ares->original_context = NULL; } if (ac == NULL) { /* Fast path from ThreadPool.*QueueUserWorkItem */ void *pa = ares->async_state; mono_runtime_delegate_invoke (ares->async_delegate, &pa, &exc); } else { MonoObject *cb_exc = NULL; ac->msg->exc = NULL; res = mono_message_invoke (ares->async_delegate, ac->msg, &exc, &out_args); MONO_OBJECT_SETREF (ac, res, res); MONO_OBJECT_SETREF (ac, msg->exc, exc); MONO_OBJECT_SETREF (ac, out_args, out_args); mono_monitor_enter ((MonoObject *) ares); ares->completed = 1; if (ares->handle != NULL) wait_event = mono_wait_handle_get_handle ((MonoWaitHandle *) ares->handle); mono_monitor_exit ((MonoObject *) ares); /* notify listeners */ if (wait_event != NULL) SetEvent (wait_event); /* call async callback if cb_method != null*/ if (ac != NULL && ac->cb_method) { void *pa = &ares; cb_exc = NULL; mono_runtime_invoke (ac->cb_method, ac->cb_target, pa, &cb_exc); MONO_OBJECT_SETREF (ac->msg, exc, cb_exc); exc = cb_exc; } else { exc = NULL; } } /* restore original thread execution context if flow isn't suppressed, i.e. non null */ if (ares->original_context) { mono_thread_set_execution_context (ares->original_context); ares->original_context = NULL; } return exc; }
/* Returns the exception thrown when invoking, if any */ static MonoObject * mono_async_invoke (ThreadPool *tp, MonoAsyncResult *ares) { ASyncCall *ac = (ASyncCall *)ares->object_data; MonoObject *res, *exc = NULL; MonoArray *out_args = NULL; HANDLE wait_event = NULL; MonoInternalThread *thread = mono_thread_internal_current (); if (ares->execution_context) { /* use captured ExecutionContext (if available) */ MONO_OBJECT_SETREF (ares, original_context, mono_thread_get_execution_context ()); mono_thread_set_execution_context (ares->execution_context); } else { ares->original_context = NULL; } if (ac == NULL) { /* Fast path from ThreadPool.*QueueUserWorkItem */ void *pa = ares->async_state; /* The debugger needs this */ thread->async_invoke_method = ((MonoDelegate*)ares->async_delegate)->method; res = mono_runtime_delegate_invoke (ares->async_delegate, &pa, &exc); thread->async_invoke_method = NULL; } else { MonoObject *cb_exc = NULL; ac->msg->exc = NULL; res = mono_message_invoke (ares->async_delegate, ac->msg, &exc, &out_args); MONO_OBJECT_SETREF (ac, res, res); MONO_OBJECT_SETREF (ac, msg->exc, exc); MONO_OBJECT_SETREF (ac, out_args, out_args); mono_monitor_enter ((MonoObject *) ares); ares->completed = 1; if (ares->handle != NULL) wait_event = mono_wait_handle_get_handle ((MonoWaitHandle *) ares->handle); mono_monitor_exit ((MonoObject *) ares); /* notify listeners */ if (wait_event != NULL) SetEvent (wait_event); /* call async callback if cb_method != null*/ if (ac != NULL && ac->cb_method) { void *pa = &ares; cb_exc = NULL; thread->async_invoke_method = ac->cb_method; mono_runtime_invoke (ac->cb_method, ac->cb_target, pa, &cb_exc); thread->async_invoke_method = NULL; exc = cb_exc; } else { exc = NULL; } } /* restore original thread execution context if flow isn't suppressed, i.e. non null */ if (ares->original_context) { mono_thread_set_execution_context (ares->original_context); ares->original_context = NULL; } #if DEBUG InterlockedDecrement (&tp->njobs); #endif if (!tp->is_io) InterlockedIncrement (&tp->nexecuted); if (InterlockedDecrement (&monitor_njobs) == 0) monitor_state = MONITOR_STATE_FALLING_ASLEEP; return exc; }