[英]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
}
}
我的问题是:
InitializeMethod()
会发生什么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
,因此您可以在WindowsForms
或wpf
中使用它,但不能在控制台应用程序中使用它,因为System.Threading.SynchronizationContext.Current
是 Z37A6259CC0C1DAE29898。
一个简单的解决方案是在主线程中创建一个不可见的控件,您的工作线程可以在该控件上调用Invoke
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.