繁体   English   中英

当我没有可用的控件时如何调用()

[英]How to Invoke() when I have no Control available

我正在编写一个连接处理程序(一个请求用户名和密码的对话框)。 该代码是一个显示对话框的处理程序。 可以从线程调用此代码,因此我需要Invoke() if InvokeRequired

在理想情况下,我可以使用Control初始化然后处理程序来执行InvokeRequired ,但有时 Control 可能是 null。 可能吗? 我该如何实现代码? 以下是正确的吗?

public class GuiCredentialsHandler
{
    // control used to invoke if needed
    private static Control mInvokeControl;

    /// <summary>
    /// Initialize a GetCredentials handler for current process.
    /// This method should be always called from the main thread, for
    /// a correctly handling for invokes (when the handler is called
    /// from a thread).
    /// </summary>
    /// <param name="parentControl">Application top form. 
    /// Can be null if unknown</param>
    public static void Initialize(Control parentControl)
    {
        if (parentControl != null)
        {
            mInvokeControl = parentControl;
        }
        else
        {
            mInvokeControl = new Control();
            // force to create window handle
            mInvokeControl.CreateControl();
        }
    }

    public static Credentials GetCredentials()
    {
        if (mInvokeControl.InvokeRequired)
        {
            return mInvokeControl.Invoke(
                new GetCredentialsDelegate(DoGetCredentials), null) 
                as Credentials;
        }
        else
        {
            return DoGetCredentials();
        }
    }

    private static Credentials DoGetCredentials()
    {
        // the code stuff goes here
    }

}

我的问题是:

  1. 如果我将 null 控件传递给InitializeMethod()会发生什么
  2. 如果在UIThread中执行了Initialize()方法,后面的代码会起作用吗?
  3. 如果您没有任何控制来测试InvokeRequired ,推荐的模式是什么?

提前致谢


编辑:做一些测试,我意识到如果我将 null 传递给Initialize() ,控件不会在 UI 线程中运行,因此 InvokeRequired 似乎返回 false。 总是。 所以我的问题是,当我无法控制时,如何执行真正的(可变的)调用?


EDIT2 :做mInvokeControl.CreateControl()解决了这个问题。

改为在该class上实施 ISynchronizeInvoke。 这是一个例子:

public class GuiCredentialsHandler : ISynchronizeInvoke
{
        //....

        private readonly System.Threading.SynchronizationContext _currentContext = System.Threading.SynchronizationContext.Current;

        private readonly System.Threading.Thread _mainThread = System.Threading.Thread.CurrentThread;

        private readonly object _invokeLocker = new object();
        //....


        #region ISynchronizeInvoke Members

        public bool InvokeRequired
        {
            get
            {
                return System.Threading.Thread.CurrentThread.ManagedThreadId != this._mainThread.ManagedThreadId;
            }
        }

        /// <summary>
        /// This method is not supported!
        /// </summary>
        /// <param name="method"></param>
        /// <param name="args"></param>
        /// <returns></returns>
        [Obsolete("This method is not supported!", true)]
        public IAsyncResult BeginInvoke(Delegate method, object[] args)
        {
            throw new NotSupportedException("The method or operation is not implemented.");
        }

        /// <summary>
        /// This method is not supported!
        /// </summary>
        /// <param name="method"></param>
        /// <param name="args"></param>
        /// <returns></returns>
        [Obsolete("This method is not supported!", true)]
        public object EndInvoke(IAsyncResult result)
        {
            throw new NotSupportedException("The method or operation is not implemented.");
        }

        public object Invoke(Delegate method, object[] args)
        {
            if (method == null)
            {
                throw new ArgumentNullException("method");
            }

            lock (_invokeLocker)
            {
                object objectToGet = null;

                SendOrPostCallback invoker = new SendOrPostCallback(
                delegate(object data)
                {
                    objectToGet = method.DynamicInvoke(args);
                });

                _currentContext.Send(new SendOrPostCallback(invoker), method.Target);

                return objectToGet;
            }
        }

        public object Invoke(Delegate method)
        {
            return Invoke(method, null);
        }

        #endregion//ISynchronizeInvoke Members

}

注意:由于 class 实现,它使用System.Threading.SynchronizationContext.Current ,因此您可以在WindowsFormswpf中使用它,但不能在控制台应用程序中使用它,因为System.Threading.SynchronizationContext.Current是 Z37A6259CC0C1DAE29898。

一个简单的解决方案是在主线程中创建一个不可见的控件,您的工作线程可以在该控件上调用Invoke

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM