问题陈述
作为开发一个应用程序的一部分,需要实施以下方案:
- 异步方法请求数据
- 用户从键盘输入数据
- 该方法接收输入结果作为函数的结果,并从同一位置继续
附加要求:不要创建其他窗口。
看起来很简单吗? 原来真的很简单。 但是首先是第一件事。
解决方案
首次尝试而不进行互联网搜索的尝试导致主线程被阻塞,因此没有任何好处。 在碰到一篇文章时 ,我正要使用ShowDialog。 作者研究了如何在WPF中制作ShowDialog。 你需要什么!
在他的文章中,他建议创建自己的ShowDialog方法实现。
[DllImport("user32")] internal static extern bool EnableWindow(IntPtr hwnd, bool bEnable); public void ShowModal() { IntPtr handle = (new WindowInteropHelper(Application.Current.MainWindow)).Handle; EnableWindow(handle, false); DispatcherFrame frame = new DispatcherFrame(); this.Closed += delegate { EnableWindow(handle, true); frame.Continue = false; }; Show(); Dispatcher.PushFrame(frame); }
我不需要窗口锁定,因为所有内容都显示在一个窗口中,并且还需要返回值。 我们删除了太多,添加了正确的...
public string GetInput() { var frame = new DispatcherFrame(); ButtonClicked += () => { frame.Continue = false; }; Dispatcher.PushFrame(frame); return Text; }
Dispatcher.PushFrame(frame)
阻止GetInput()
方法GetInput()
直到frame.Continue
变为false
为止。 当开始新的帧时,主循环暂停并且开始新的帧。 该循环处理系统消息,而主循环中的执行点不再移动。 当我们退出当前帧( frame.Continue = false
)时,主循环将从同一位置继续工作。
现在只剩下检查性能了。
在MainWindow中,创建一个按钮并在其上挂起一个处理程序,这将启动任务,在该任务中,我们将转向键盘输入。
处理程序代码:
public RelayCommand ButtonClick => new RelayCommand(() => { Task.Factory.StartNew(() => {
我使用此解决方案输入了验证码和用于双重身份验证的其他代码。 但是可能会有大量的应用程序。
! 该示例代码包含违反mvvm原理的行为,并且 不要用力 缺少设计
Github源代码: 概念验证
有用的链接
文章“自定义ShowDialog”
使用机器翻译的DispatcherFrame类的简短描述
本文提供了通过等待来等待完成。