コード例 #1
0
        private static void OnStabilized(IntPtr context, IntPtr table)
        {
            Interop.IpHlpApi.FreeMibTable(table);

            TeredoHelper helper = (TeredoHelper)GCHandle.FromIntPtr(context).Target !;

            // Lock the TeredoHelper instance to ensure that only the first call to OnStabilized will get to call
            // RunCallback.  This is the only place that TeredoHelpers get locked, as individual instances are not
            // exposed to higher layers, so there's no chance for deadlock.
            if (!helper._runCallbackCalled)
            {
                lock (helper)
                {
                    if (!helper._runCallbackCalled)
                    {
                        helper._runCallbackCalled = true;

                        ThreadPool.QueueUserWorkItem(o =>
                        {
                            TeredoHelper helper = (TeredoHelper)o !;

                            // We are intentionally not calling Dispose synchronously inside the OnStabilized callback.
                            // According to MSDN, calling CancelMibChangeNotify2 inside the callback results into deadlock.
                            helper.Dispose();

                            helper._callback.Invoke(helper._state);
                        }, helper);
                    }
                }
            }
        }
コード例 #2
0
        // Returns true if the address table is already stable.  Otherwise, calls callback when it becomes stable.
        // 'Unsafe' because it does not flow ExecutionContext to the callback.
        public static unsafe bool UnsafeNotifyStableUnicastIpAddressTable(Action <object> callback, object state)
        {
            Debug.Assert(callback != null);

            TeredoHelper?helper = new TeredoHelper(callback, state);

            try
            {
                uint err = Interop.IpHlpApi.NotifyStableUnicastIpAddressTable(AddressFamily.Unspecified,
                                                                              out SafeFreeMibTable table, &OnStabilized, GCHandle.ToIntPtr(helper._gcHandle), out helper._cancelHandle);

                table.Dispose();

                if (err == Interop.IpHlpApi.ERROR_IO_PENDING)
                {
                    Debug.Assert(helper._cancelHandle != null && !helper._cancelHandle.IsInvalid);

                    // Suppress synchronous Dispose. Dispose will be called asynchronously by the callback.
                    helper = null;
                    return(false);
                }

                if (err != Interop.IpHlpApi.ERROR_SUCCESS)
                {
                    throw new Win32Exception((int)err);
                }

                return(true);
            }
            finally
            {
                helper?.Dispose();
            }
        }